I am having trouble with this program. I'm not so familiar with the functions strcpy and strcmp.
Can any professionals help me or give me some advice?
As others have stated, choose either C-style strings or C++ std::string.
I highly recommend not creating a separate function for searching the string array because passing arrays to functions is difficult for beginners.
Try something like:
#include <string>
#include <iostream>
#define MAX_NAMES 16
int main(void)
{
std::string name_container[MAX_NAMES];
unsigned int names_in_container = 0;
while (1)
{
std::string name_from_user;
std::cout << "Enter name: ";
if (!getline(std::cin, name_from_user))
{
break; // Exit from the "while" loop
}
// Search the name container for the name.
unsigned int array_slot = 0;
bool name_found = false;
for (array_slot = 0; array_slot < names_in_container; ++array_slot)
{
if (name_from_user == name_container[array_slot])
{
std::cout << "\nName exists in slot " << array_slot << "\n";
name_found = true;
}
}
if (!name_found)
{
if (array_slot >= MAX_NAMES)
{
std::cout << "Name container full, cannot add name.\n";
break;
}
else
{
name_container[names_in_container] = name_from_user;
++names_in_container;
}
}
}
}
Please recognize that you are comingling C++ string (std::string) and the C library strcpy and strcmp functions. They are two different things. You probably need to look at some of the methods available under the std::string class (.c_str, =, ==),
Here are a few comments, and suggestions,
void search (string sid[], //do you intend to pass a string sid, or an array of srings?
string name[], //do you intend to pass a string name, or an array of strings?
int No_of_data_input)
{
char id[100];
string input;
char namename[100];
//comments ignored/removed
//these two lines declare the function strcpy
char * strcpy ( char * namename, const char * name );
char * strcpy ( char * id, const char * sid );
//do you intend to copy name and sid instead?
//do you want: strcpy(namename, name[i].c_str() );
//do you want: strcpy(id, sid[i].c_str() );
//if so, you want to do this inside your loop on i, below,
int sameName=0;
int j=0;
cout<<"enter id or name";
getline(cin,input); //you probably want: cin >> input;
//do you intend to declare the function strcpy yet again?
char * strcpy ( char * inputinput, const char * input );
//or do you intend to copy input to some char[]?
//you probably want: strcpy( inputinput, input.c_str() );
//you probably want number of elements in sid[] or name[]?
for(int i=0;i<4;i++){
//you probably want sid[i] here
if ((strcmp(inputinput,id[i])==0) || (strcmp(inputinput,name[i])==0)){
//you could rewrite this as:
//if( (input == id[i]) || (input == name[i]) ){
sameName++;
j=i;
} //do us a favor
} //make the ending braces clearer
cout<<sameName;
if (sameName==0)
cout<<"No student found: ";
else if (sameName==1)
cout<<"student found: "<<name[j]<<endl<<id[j];
else if (sameName>1)
cout<<"More than one student found,please enter id";
}
Do you want (or need) to comingle std::string and strcpy, strcmp?
Editing your code, you might want to just use std::string,
void search (string sid[], //do you intend to pass an array of srings?
string name[], //do you intend to pass an array of strings?
int count)
{
string input;
int same=0;
int j=0;
cout<<"enter id or name";
cin >> input;
//you probably want number of elements in sid[] or name[]?
for(int i=0;i<count;++i){
if( (input == sid[i]) || (input == name[i]) ){
++same;
j=i;
}
}
cout<<"same: "<<same<<endl;
if (same==0)
cout<<"No student found: "<<endl;
else if (same==1)
cout<<"student found: "<<name[j]<<","<<id[j]<<endl;
else if (same>1)
cout<<"More than one student found,please enter id"<<endl;
}
Maybe you could use a vector of strings? Then you could use an iterator on the vector.
You may have more success if you define a student record (containing sid and name), and pass a vector of student records. Then use an iterator over that vector -- read about vector and iterators.
Related
I've been trying to bend my head around this problem for a week now, but I can't seem to find anything online and I've given up on trying to solve it on my own.
My assignment is to write a program which will read names from a file and accept new entries from the user, then sort the entires and write them out to the file. The only crux about this is that I have to sort them in a function and use pointers to do so. This code is supposed to be written in C++ aswell, using character arrays.
The code I have right now looks like this. This is a working version, the only problem is that I don't use neither pointers or a function to sort the names.
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<cstring>
bool sorted;
using namespace std;
int main()
{
int i = 0;
int numNames = 0;
ifstream ifs;
ifs.open("namn.txt");
char c[20][20];
if(ifs.is_open())
{
while(!ifs.eof())
{
ifs >> c[i];
i++;
}
}
cout<<"How many names do you want to enter?"<<endl;
cin>>numNames;
for(int l = i-1; l<numNames+i-1; l++)
{
system("cls");
cout<<"Enter a name: ";
cin>>c[l];
}
while(sorted == false)
{
for(int j = 0; j<numNames+i-1; j++)
{
for(int k = j; k<numNames+i-1; k++)
{
if(c[j][0] > c[k][0])
{
char snorre[20];
strcpy(snorre,c[j]);
strcpy(c[j],c[k]);
strcpy(c[k],snorre);
}
else if(c[j][0] == c[k][0])
{
if(c[j][1] > c[k][1])
{
char snorre[20];
strcpy(snorre,c[j]);
strcpy(c[j],c[k]);
strcpy(c[k],snorre);
}
}
}
}
cout<<endl<<endl<<endl;
ofstream ofs;
ofs.open("namn.txt");
for(int o = 0; o<numNames+i-1; o++)
{
cout<<c[o]<<" ";
ofs<<c[o]<<endl;
}
ofs.close();
system("pause");
sorted = true;
}
}
So hopefully someone could help me out with this problem, thanks in advance! :)
To get your code to use pointers and functions, you can do this- you should change your code and make it use the following:
First, Get each name from the file to an std::string, using getline(ifstream_object, std::string_object), for reference see here.
Convert each one to a const char * (also shown in that example), using .c_str().
Do the following to each of the new names entered.
Store all names entered in this array pointers: char *names[20];, like this: names[i] = name;
Next, Create a function such as follows:
int location_of_bigger_string(const char* s1, const char* s2)
{
// Returns 1 if s1 should be before s2 and 2 otherwise
// This way, you use functions and pointers together.
// Use strcmp(s1,s2) here to determine returning value
}
strcmp(char*, char*) - read about it here.
Finally, to sort all the strings, use qsort or this example.
Here's the complete code,
Note that the compare function gets pointers to the elements, here the elements are pointers themselves, so what's passed to "compare" function is of type "char **"
{
#include "stdafx.h"
#include<iostream>
//retruns +1 if str1 > str2 alphabetically
int compare(const void * a, const void * b )
{
const char * str1 = *((const char **)a);
const char * str2 = *((const char **)b);
int i;
for ( i = 0 ; str1[i] && str2[i] ; i++ )
{
if ( str1[i] > str2[i] )
{
return +1;
}
else if ( str1[i] < str2[i] )
{
return -1;
}
}
//one or both strings have ended
if (str1[i]) //str1 is longer
return +1;
else if (str2[i]) //str2 is longer
return -1;
else
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char * names[]={"Zebra","Kousha","Koosha","Kou","Koush","Test"};
qsort( names, 6, sizeof(char *), compare );
return 0;
}
}
I'm supposed to be writing code that takes a string of comma separated values without spaces (ex. my,name,is,jack). First we had to write a function
string nextstring(string str, int start_index)
that returns a single "value" from your initial string depending on the start index. The second part of the problem was to write a function
int split(string str, string a[], int max_size)
that will identify all the values in the initial string and put them in a string array and then return the total number of values stored in the array; i.e. if you had initially input my,name,is it would return 3.
My function never returns the correct value and whatever it returns changes depending on what the length of the words are.
#include <iostream>
#include <string>
using namespace std;
string nextstring(string str, int start_index);
int split(string str, string a[], int max_size);
int main()
{
string str;
int cnt;
string a[100];
cout<< "what is your string" << endl;
getline(cin, str);
cnt= split(str, a, 100);
cout << "There are " << cnt << " values in this string" << endl;
for(int i=0; i<cnt; i++)
{
cout << a[i] << endl;
}
return 0;
}
string nextstring(string str, int start_index)
{
string ans;
if(str[start_index] == ',' || str[start_index] == '\0')
{
ans=" ";
}
else{
ans=str[start_index]+nextstring(str, start_index+1);
}
return ans;
}
int split(string str, string a[], int max_size)
{
int j=0;
int ans=0;
double k=0;
while(j<max_size)
{
a[j]= nextstring(str,k);
string check=a[j];
if(isalpha(check[0])!= 0)
{
ans++;
}
k=k+a[j].length();
j++;
}
return ans;
}
It seems that your problem is that while(j<max_size){...} leads to j being incremented up to max_size. The line a[j]= nextstring(str,k); is at some points reading values that are outside your string which is really bad!
Replacing while(j<max_size){...} by while(j<max_size && k<str.length()){...} seems to be enough to make your code work!
Apart from that:
k has no reason to be a double! It should be an int (or something similar).
Since you are already using string, you should also learn to use vector. split is better written as:
int split(string str, vector<string> &a, int max_size)
{
int ans=0;
int k=0;
while(k<str.length())
{
string next = nextstring(str,k);
if(isalpha(next[0])!= 0)
{
ans++;
a.append(next);
}
k += next.length();
}
return ans;
}
The problem in your approach is to identify the end of the string, as there is no null terminator in a c++ string. Consider to update nextstring() to look for the end of string in a different manner:
string nextstring(string str, int start_index)
{
...
if(start_index == str.size() || str[start_index] == ',' ) //<===
{
ans=" ";
}
...
}
online demo
Additional recommendation
Note that it is not very nice to return a blank string when in reality it should be empty to reflect its real value (e.g. ",,"). You have no choice because otherwise you would have no mean in the calling function, to determine that the end of string was reached. But the consequence is thar all your strings have a trailing blank.
When you call recursively the function adding char to build the return string, you risk to have a considerable overhead. You could consider avoiding this, by replacing the else part:
ans=str.substr(start_index, str.find(',', start_index+1)-start_index);
However, as you have no trailing blank anymore, you need to adapt split() so to adapt its way to count the total number of chars parsed:
k=k+a[j].length()+1; // +1 because there's no longer a trailing blank.
Online demo
So, i have to do this project for college. I have to write a program that manages the orders of a pizza restaurant. so far this is what i have done :
#include <iostream>
#include <array>
#include <string>
#include <cctype>
#include <cmath>
#include <locale>
#include <algorithm>
using namespace std;
const int MAX_INGREDIENTES_PIZZA=10;
const int MAX_PEDIDOS=20;
enum TIngrediente
{
TOMATE,
QUESO,
NATA,
CEBOLLA,
POLLO,
HUEVO,
SALAMI,
ANCHOA,
BACON,
GAMBA
};
struct TPedido
{
string nombre_cliente;
int telefono;
int numero_pedido;
int numero_ingredientes;
TIngrediente ingredientes;
};
typedef array<float, MAX_PEDIDOS> listado_pedidos;
const array<string, MAX_INGREDIENTES_PIZZA> TIngredientes2 = {{"tomate", "queso", "nata", "cebolla", "pollo", "huevo", "salami", "anchoa", "bacon", "gamba"}};
TIngrediente StrToIngrediente(string s);
string IngredienteTostr(TIngrediente c);
string tolower(string s);
string tolower(string s)
{
string r = s;
for (int i = 0; i < s.size(); ++i)
r[i] = tolower(r[i]);
return r;
}
TIngrediente StrToIngrediente(string s)
{
s=tolower(s);
int i;
while (i < TIngredientes2.size() and TIngredientes2[i] != s)
++i;
return (TIngrediente)i;
}
string IngredienteTostr(TIngrediente c)
{
return TIngredientes2[c];
}
TIngredientes2 leer_ingrediente()
{
TIngredientes2 r;
for (int i=0; i<MAX_INGREDIENTES_PIZZA;i++){
cin>>r[i];
r[i]=tolower(r[i]);
}
StrToIngrediente(TIngredientes2);
return r;
}
TIngredientes2 escribir_ingrediente()
{
TIngredientes2 s;
for(int i=0; i<s.size(); i++){
cout<<s[i]<<endl;
}
return s;
}
TPedido leer_pedido()
{
TPedido p;
string ingredientes;
bool ok=true;
getline (cin, p.nombre_cliente);
cin >> p.telefono;
cin >> p.numero_pedido;
cin >> p.numero_ingredientes;
cin.ignore(100,'\n');
//getline (cin, p.ingredientes);
StrToIngrediente(ingredientes);
//necesitamos inicializar la variable booleana
if( numero_ingredientes > MAX_INGREDIENTES_PIZZA)
ok=false;
else if (numero_pedido > MAX_PEDIDOS)
ok=false;
else if (ingredientes != TIngrediente[i])
ok=false;
return p;
}
OK, But im having a few issues :
1) i have declared TIngredientes2 as an array, but the compiler says to me Tingredientes2 does not name a type.
2) I have managed to write the functions that transforms String in TIngrediente (enum) and viceversa, but now i have to make 2 functions to read keyboard input/write in screen and i dunno how to use those functions. I have writen something below but i dont know if it is ok.
3) When it comes to read keyboard input in leer_pedido() i dont know if that is ok because of the struct and most important, i have no idea how to use the boolean to say if the data introduced is correct or not.
4) The next fuction consist in storing the data from the last fucntion leer_pedido() in a list, and i have no clue.
I hope someone can help me
1) Function can't return an object of type 'Ttingrediente2' if you haven't already made class of type 'Tingrediente2'.
In your function :
TIngredientes2 escribir_ingrediente()
{
TIngredientes2 s;
for(int i=0; i<s.size(); i++){
cout<<s[i]<<endl;
}
You're declaring variable 'Tingredientes s' and after it,you're printing it out on the screen but it hasn't got size (there are no elements inside s).
Try like this:
void escribir_ingrediente(array<string,MAX_INGREDIENTES_PIZZA> s)
{
for(int i=0; i<s.size(); i++)
cout<<s[i]<<endl;
}
where you are passing already existing array to a function and it's printing out elements of s array.
2) Just read more about enumerations,iterating over them and inserting new elements.
3) You're using boolean variable on the beginning of testing your user's input.Something like:
bool good_Input = true; // suppose user's input is ok
if( p.numero_ingredientes > MAX_INGREDIENTES_PIZZA || p.numero_pedido > MAX_PEDIDOS)
good_input=false; // input is not good if there is more ingredients than max number of ingredients
if(good_Input)
cout<<"Input is good"<<endl;
else cout << "Input is not good"<<endl;
Therefore,you are leading boolean variable through your code so if there may be a mistake,you change it's value to 'false' and it will be 'false' to the end so you will know how to handle it further in code.
4) Storing structure's data in vector is the most easiest way to do that:
vector<Tpedido> structuresVector;
sturcturesVector.push_back(leer_pedido());
leer_pedido function returns 'Tpedido' type so you can insert it in vector directly
I tried to use,
if(isalpha(card[i].name))
...
but it says that i can't use it with char type here is my code:
This is the struct:
struct firm {
unsigned egn;
char name[80];
char lastname[80];
char department[80];
unsigned salary;
}card[100];
This is the function where i want to make the check if only letters then to continue:
void enter()
{
int i, n;
char temp[80];
do{
cout<<"Enter how many workers you want to add: ";cin>>n;
}while(!(n>0 && n<101));
for(i=top;i<n;i++)
{/*ЕГН + проверка*/
cout<<"Enter EGN: ";do{
cin>>temp;
if((strlen(temp)!=10))
cout<<"Enter EGN: ";
}while(strlen(temp)!=10);
card[i].egn = (unsigned) atoi (temp);
/*Име Фамилия*/
cout<<"Enter name(only letters): ";cin>>card[i].name;
cout<<"Enter lastname(only letters): ";cin>>card[i].lastname;
cout<<"Enter department: ";cin>>card[i].department;
cout<<"Enter salary: ";cin>>temp;
card[i].salary = (unsigned) atoi (temp);
}
}
When i try to use this kind of code:
cout<<"Enter name(only letters): ";do{
cin>>card[i].name;
if(isalpha(card[i].name))
.....;
and it says that i can't use char in int (isalpha uses int? )
You need to loop over every character of the string, isalpha() only tests a single character.
You cannot use isalpha on an entire char array, only on individual characters. To check that every character in a char array is alphabetical, you can use the std::all_of algorithm:
auto name_begin = std::begin(card[i].name);
auto name_end = std::end(card[i].name);
bool name_alpha = std::all_of(name_begin, std::find(name_begin, name_end, '\0'), std::isalpha);
if (name_alpha) {
std::cout << "It's alphabetical!" << std::endl;
}
If you're using a compiler without the necessary C++11 support, you can do:
char* name_begin = card[i].name;
bool name_alpha = std::all_of(name_begin, name_begin+std::strlen(name_begin), std::isalpha);
if (name_alpha) {
std::cout << "It's alphabetical!" << std::endl;
}
Then the boring way without using the standard library algorithms:
bool name_alpha = true;
for (char* character = card[i].name; *character != '\0'; character++) {
if (!std::isalpha(*character)) {
name_alpha = false;
break;
}
}
if (name_alpha) {
std::cout << "It's alphabetical!" << std::endl;
}
The problem is that name is itself an array of chars, so you need to test each each element something like this:
.....
cout<<"Enter name(only letters): ";do{
cin>>card[i].name;
bool bIsAlpha = true;
for (int j = 0; j < strlen(card[i].name); ++j)
{
if(!isalpha(card[i].name[j]))
{
bIsAlpha = false;
break;
}
}
if (bIsAlpha)
{
.....;
}
I'm trying to compare a character array against a string like so:
const char *var1 = " ";
var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
This if statement never validates as true... when I output var1 it is "dev", I was thinking maybe it has something to do with a null terminated string, but the strlen of "dev" and var1 are equal... I also thought maybe var1 == "dev" was comparing "dev" against the memory location of var1 instead of the value. *var1 == "dev" results in an error.... tried many things, probably a simple solution for the saavy c++ developer (I havent coded c++ in a looong time).
edit:
we've tried
if(strcmp(var1, "dev") == 0)
and
if(strncmp(var1, "dev", 3) == 0)
Thanks
edit: After testing at home I'm just going to suggest my co-worker changes the datatype to a string. I believe he was comparing a char array of a large size against a string. I put together a program that outputs sizeof, strlen, etc to help us work through it. Thanks to everyone for the help.
Use strcmp() to compare the contents of strings:
if (strcmp(var1, "dev") == 0) {
}
Explanation: in C, a string is a pointer to a memory location which contains bytes. Comparing a char* to a char* using the equality operator won't work as expected, because you are comparing the memory locations of the strings rather than their byte contents. A function such as strcmp() will iterate through both strings, checking their bytes to see if they are equal. strcmp() will return 0 if they are equal, and a non-zero value if they differ. For more details, see the manpage.
You're not working with strings. You're working with pointers.
var1 is a char pointer (const char*). It is not a string. If it is null-terminated, then certain C functions will treat it as a string, but it is fundamentally just a pointer.
So when you compare it to a char array, the array decays to a pointer as well, and the compiler then tries to find an operator == (const char*, const char*).
Such an operator does exist. It takes two pointers and returns true if they point to the same address. So the compiler invokes that, and your code breaks.
IF you want to do string comparisons, you have to tell the compiler that you want to deal with strings, not pointers.
The C way of doing this is to use the strcmp function:
strcmp(var1, "dev");
This will return zero if the two strings are equal. (It will return a value greater than zero if the left-hand side is lexicographically greater than the right hand side, and a value less than zero otherwise.)
So to compare for equality you need to do one of these:
if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}
However, C++ has a very useful string class. If we use that your code becomes a fair bit simpler. Of course we could create strings from both arguments, but we only need to do it with one of them:
std::string var1 = getenv("myEnvVar");
if(var1 == "dev")
{
// do stuff
}
Now the compiler encounters a comparison between string and char pointer. It can handle that, because a char pointer can be implicitly converted to a string, yielding a string/string comparison. And those behave exactly as you'd expect.
In this code you are not comparing string values, you are comparing pointer values. If you want to compare string values you need to use a string comparison function such as strcmp.
if ( 0 == strcmp(var1, "dev")) {
..
}
"dev" is not a string it is a const char * like var1. Thus you are indeed comparing the memory adresses. Being that var1 is a char pointer, *var1 is a single char (the first character of the pointed to character sequence to be precise). You can't compare a char against a char pointer, which is why that did not work.
Being that this is tagged as c++, it would be sensible to use std::string instead of char pointers, which would make == work as expected. (You would just need to do const std::string var1 instead of const char *var1.
There is more stable function, also gets rid of string folding.
// Add to C++ source
bool string_equal (const char* arg0, const char* arg1)
{
/*
* This function wraps string comparison with string pointers
* (and also works around 'string folding', as I said).
* Converts pointers to std::string
* for make use of string equality operator (==).
* Parameters use 'const' for prevent possible object corruption.
*/
std::string var0 = (std::string) arg0;
std::string var1 = (std::string) arg1;
if (var0 == var1)
{
return true;
}
else
{
return false;
}
}
And add declaration to header
// Parameters use 'const' for prevent possible object corruption.
bool string_equal (const char* arg0, const char* arg1);
For usage, just place an 'string_equal' call as condition of if (or ternary) statement/block.
if (string_equal (var1, "dev"))
{
// It is equal, do what needed here.
}
else
{
// It is not equal, do what needed here (optional).
}
Source: sinatramultimedia/fl32 codec (it's written by myself)
your thinking about this program below
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
//outputs:
//
//Looking for R2 astromech droids...
//found R2D2
//found R2A6
when you should be thinking about inputting something into an array & then use strcmp functions like the program above ... check out a modified program below
#include <iostream>
#include<cctype>
#include <string.h>
#include <string>
using namespace std;
int main()
{
int Students=2;
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
int Grades[Students][Projects];
for(int j=0; j<=Projects-1; j++){
for(int i=0; i<=Students; i++) {
cout <<"Please give grade of student "<< j <<"in project "<< i << ":";
cin >> Grades[j][i];
}
Sum2 = Sum2 + Grades[i][j];
Avg2 = Sum2/Students;
}
SumT2 = SumT2 + Avg2;
AvgT2 = SumT2/Projects;
cout << "avg is : " << AvgT2 << " and sum : " << SumT2 << ":";
return 0;
}
change to string except it only reads 1 input and throws the rest out
maybe need two for loops and two pointers
#include <cstring>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
char name[100];
//string userInput[26];
int i=0, n=0, m=0;
cout<<"your name? ";
cin>>name;
cout<<"Hello "<<name<< endl;
char *ptr=name;
for (i = 0; i < 20; i++)
{
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
}
int length = 0;
while(name[length] != '\0')
{
length++;
}
for(n=0; n<4; n++)
{
if (strncmp(ptr, "snit", 4) == 0)
{
cout << "you found the snitch " << ptr[i];
}
}
cout<<name <<"is"<<length<<"chars long";
}