Is this a misunderstanding of the functionality of strcpy()? - c

#include <stdio.h>
#include <string.h>
int main(void) {
int number_of_members;
char family[number_of_members][20][number_of_members][20];
char member_name[20];
char birth_state[20];
char family_last_name[20];
printf("What is the last name of the family?\n");
scanf("%s", &family_last_name);
printf("How many members do you want to create?\n");
scanf("%d", &number_of_members);
int const FAMILY_SIZE = number_of_members;
number_of_members = number_of_members -1;
printf("Enter the family member name: \n");
for(number_of_members;number_of_members>-1;number_of_members--)
{
scanf("%s", &member_name);
strcpy(family[number_of_members], member_name);
printf(" %d %s %s\n",number_of_members, member_name, family_last_name);
}
printf("%s, %s ", family[0], family[1]);
return 0;
}
Here is the output:(from Ideone.com)
Ideone.com with code
The input to this code is: Layne , 2 , tim , jim.
When run, it shows the correct index with the name in the array however, once out it will show the last entered name, jim, as family1 and family[0]. Am I not understanding how strcpy() works? or is it a logic error?Some assistance soon would be appreciated!

This is very very wrong
int number_of_members;
char family[number_of_members][20][number_of_members][20];
Because you haven't initialized number_of_members.
Because it doesn't make sense whatsoever, it's not possible that you really need this kind of array.
And yes, if you enable compiler warnings it will hit you in your nose with a stick, because
strcpy(family[number_of_members], member_name);
shouldn't even compile and is undefined behavior since the type of family[number_of_members], is an array of arrays of arrays of char.
strcpy can take an array of char's because it will be automatically converted to a char poitner, and provided that the contents of the array comply with what a c string is, then strcpy() will work correctly, in your case the behavior is undefined because almost surely the '\0' will never be found in the destination pointer.

instead of
int num_of_members;
char family[number_of_members][20][number_of_members][20];
which is not C code, do this
#define MAX_MEMBERS 20
char family[MAX_MEMBERS][20];
which creates a rectangular array of arrays each of 20 bytes long

Related

Storing user defined string into specific 2d array location in C

I am learning 2d arrays in C and im trying to get the user's name in C and store it in a 2d array. I found out that C don't have String data type and can only accepts string with data type char.
Now I am successful in getting the name from the user but i can't store the name into the separate 2d array. Here the code i tried:
#include <stdio.h>
#include <cstring>
int main()
{
int to=0,y=1,z=0,end=0;
char *ticketS[100][3];
char name[50];
printf("\nENTER PASSENGER'S NAME: ");
gets(name);
printf("%s",name);
strcpy(ticketS[z][0], name);
printf("%s", ticketS[z][0]);
return 0;
}
My input is: test name
My expected output is:
test name
test name
The actual output is:
test name
I can't seem to find any examples regarding my problem. Any help would be greatly appreciated.
Assuming you wanted to create 2 arrays with 100 chars each, and copy the name given by the user to the 2D array:
#include <stdio.h>
#include <string.h>
int main()
{
int to=0,y=1,z=0,end=0;
char ticketS[2][100];
char name[50];
printf("\nENTER PASSENGER'S NAME: ");
gets(name);
printf("%s\n",name);
strcpy(ticketS[0], name); // a for-loop would work as well
strcpy(ticketS[1], name);
printf("%s\n%s\n", ticketS[0], ticketS[1]);
return 0;
}
A few things you should pay attention to:
The indexing is wrong. char *ticketS[100][3]; creates 100 arrays with 3 chars each.
Using char *ticketS[100][3]; you just declare the variable, however, you don't initialize it
Null-terminator '\0' here plays a role. strcpy copies until it finds a Null-terminator. Therefore, to get your wanted result you would need to copy the string a few times, or use a different copying method (not strcpy).
This is also why I used %s twice with printf.
In the code exmaple I gave, ticketS[0] is a pointer to the 1st 100 char array.
Hope you find this useful.

Char arrays and scanf function in C

I expected to get errors in following code, but I did not. I did not use & sign. Also I am editing array of chars.
#include <stdio.h>
int main()
{
char name[10] ="yasser";
printf("%s\n",name);
// there is no error ,
// trying to edit array of chars,
// also did not use & sign.
scanf("%s",name);
// did not use strcpy function also.
printf("%s\n",name);
return 0;
}
I expected to get errors in following code, but I did not.I did not use & sign.
scanf("%s",name);
That's totally ok as name is already the address of the character array.
It sounds like you have several questions:
calling scanf("%s", name) should have given an error, since %s expects a pointer and name is an array? But as others have explained, when you use an array in an expression like this, what you always get (automatically) is a pointer to the array's first element, just as if you had written scanf("%s", &name[0]).
Having scanf write into name should have given an error, since name was initialized with a string constant? Well, that's how it was initialized, but name really is an array, so you're free to write to it (as long as you don't write more than 10 characters into it, of course). See more on this below.
Characters got copied around, even though you didn't call strcpy? No real surprise, there. Again, scanf just wrote into your array.
Let's take a slightly closer look at what you did write, and what you didn't write.
When you declare and initialize an array of char, it's completely different than when you declare and initialize a pointer to char. When you wrote
char name[10] = "yasser";
what the compiler did for you was sort of as if you had written
char name[10];
strcpy(name, "yasser");
That is, the compiler arranges to initialize the contents of the array with the characters from the string constant, but what you get is an ordinary, writable array (not an unwritable, constant string constant).
If, on the other hand, you had written
char *namep = "yasser";
scanf("%s", namep);
you would have gotten the problems you expected. In this case, namep is a pointer, not an array. It's initialized to point to the string constant "yasser", which is not writable. When scanf tried to write to this memory, you probably would have gotten an error.
When you pass arrays to functions in C, they decay to pointers to the first item.
Therefore for:
char name[] ="yasser";
scanf("%s", name) is the same as scanf("%s", &name[0]) and either of those invocations should send shivers down your spine, because unless you control what's on your stdin (which you usually don't), you're reading a potentially very long string into a limited buffer, which is a segmentation fault waiting to happen (or worse, undefined behavior).
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char *myName = (char *) calloc(10, sizeof(char));
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
printf("%s\n",myName);
scanf("%s",myName);
printf("%s\n",myName);
return (EXIT_SUCCESS);
}
#include <stdio.h>
#include <string.h>
int main()//fonction principale
{
char name[10] ="yasser";
int longeur=0;
printf("%s\n",name);
scanf("%s",name);
longeur = strlen(name);
for (int i=0;i<longeur;i++) {
printf("%c",*(name+i));
}
return 0;}

I can't seem to print out a string from a structure but I can print an integer

My code is suppose to get the names of students and the student grade. After that I try to print the student names from the structure that I made and I can only get the grade to print. I get an error when trying to print the string using
printf("%s", test[0].names);
and the error says,
Unhandled exception at 0x0fe113af (msvcr100d.dll) in StudentNamesAndGrades.exe: 0xC0000005: Access violation reading location 0x65736f4a.
But when I use
printf("%d", test[0].studentScores);
It prints out the score of the first student. Here is the entire code because it might be something other than the way I'm trying to print it out.
#include <stdio.h>
#include <string>
/*
this program will get a name of students
and then you will enter the grade for each one :)
*/
struct students
{
char *names;
int studentScores;
};
int main(void)
{
int numStudents = 0;
students *test;
int i;
printf("Enter the number of students in your class: ");
scanf("%d", &numStudents);
test = (students*)malloc(numStudents * sizeof(students));
printf("Enter the names of the %d students\n", numStudents);
for (i = 0; i < numStudents; i++)
{
printf("Enter the name of student %d: ", i + 1);
scanf("%s", &test[i].names);
printf("Enter the students score: ");
scanf("%d", &test[i].studentScores);
}
printf("%d", test[0].studentScores);
printf("%s", test[0].names); // This is where I get a problem :/
return 0;
}
You did not allocate memory for char *names; while taking input at all.
Your struct could be like:
typedef struct students
{
char names[30];
int studentScores;
}students;
Also using fgets is safer than using scanf.
You need to allocate space for the names field, but I would recommend a different approach
struct students
{
char names[100];
int studentScores;
};
and then change the scanf() to
scanf("%99s", test[i].names);
there is another mistake in your first scanf() your are passing the address to the pointer, instead of the pointer.
You should use the address of & operator for the integer, because you need to pass a pointer to an integer for the "%d" specifier, but your names field variable was already a pointer, so no neet to take it's address.
Some other tips you might be interested in
Don't cast the result of malloc, although it seems that you are erroneously using a c++ compiler to compile c code, and in c++ you do need the cast, in c you don't, it makes your code harder to read and other problems which you can read with the most popular c question on Stack Overflow.
Check the return value from malloc, it doesn't matter how unlikely it could fail, since it could theoretically fail, you must check it's return value, which is NULL on failure.

Pointer trouble, argument errors and general trouble in a very simple code

I recently got an assignment to write a code in C that determines if a list of words is sorted or not ("sorted"= all the words are in rising order of letters within the word)
We have many guidelines we have to follow, so the end result is outright stupid, instead of a short and efficient code.
I am getting 2 errors with my code:
"Passing argument 1 of 'sortedsentance' makes pointer from integer without a cast"
expected 'char *' but argument is of type 'char'
Here is my code-
#include <stdio.h>
int sortedSentance(char *str)
{
int i;
for (i=1; str[i]!='0'; i++)
{
if ((str[i]>str[i-1])||(str[i]==33))
continue;
else
break;
}
if (str[i]=='\0')
return 1;
else
return 0;
}
int main()
{
int num=0, val=0;
char str1;
printf("Please enter the number of strings of length 5 (maximum 5)\n");
scanf("%d", &num);
printf("Please enter %d strings\n", num);
scanf("%s", &str1);
val= (sortedSentance(str1));
if (val==1)
printf("the string %s, is sorted.", str1);
else
printf("the string %s, is not sorted.", str1);
return 0;
}
Notes:
Our guidelines press the function has to be declared like that, i know it should be done differently.
I know the variable num doesn't do anything, but again, for the sake of the stupid guidelines. The algorithm does it's desired function even without actually receiving the number of words from beforehand.
Any help would be much appreciated, I'm already grasping my hairs trying to make sense of why doesn't this very simple code work, and what kind of stupid mistake could i have done.
The problem is with your
char str1;
You try to use single char but in your function it accepts a pointer to a char array. This is the problem you have two options.
char str1[100];//This 100 could be changed according to your needs
2.
char * str1 = new char[100];//This 100 could be changed according to your needs
Either will work and remember to calls delete [] operator on str1 in the second case.
Moreover, I did't looked at logical correctness of your program. Just resolved your compilation error.
P.S.
Since the solution needs to be in C,
you may use
char * str1 = malloc(sizeof(char)*(100));
Instead of char str1; that is a holder for a single character you should allocate memory for a string, you can choose :
Static memory allocation : char str1[100];
Dynamic memory allocation : char *str1 = (char*) malloc(sizeof(char) * 100);
P.S. You don't have to pass to scanf the address of the string, because str1 is an address itself so write scanf("%s", str1); instead of scanf("%s", &str1);

Argument of type "char" is incompatible with parameter of type char*

I keep receiving this error and unsure how to fix it. I'm new to C programming and tried searching through the book/internet and couldn't find much help. I'm trying to create a program that will print a grade report using a loop and a sctructure
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Grades
{
char Name[20];
char Hrs;
int ID;
char ClassName[20];
char Grade;
char ClassID[6];
};
int main ()
{
struct Grades Transcript[6];
int classCnt = 0;
int vHrs=0;
char vGrade[2];
char vName[20], vCID[6], vClassName[20];
printf("Enter Students Name: ");
fgets(vName, 20, stdin);
do
{ printf("Enter Class ID; ");
fgets(vCID, 6, stdin);
strcpy_s(Transcript[classCnt].ClassID, vCID);
printf("Enter Class Name: ");
fgets(vClassName, 20, stdin);
strcpy_s(Transcript[classCnt].ClassName, vClassName);
printf("Enter Class Hours: ");
scanf("%d", &vHrs);
strcpy(Transcript[classCnt].Hrs, vHrs); //Problem occurs here
printf("Enter Class Grade: ");
scanf("%c", vGrade);
strcpy(Transcript[classCnt].Grade, vGrade); //Problem occurs here
classCnt++;
}while(classCnt<=6);
}
You actually have a number of problems here:
First, strcpy() is used to copy a string, if you have a character and you want it to assign it, you can simply assign it with the = operator. The strcpy() function is used when you have a character array you want to assign.
So your first problem
strcpy(Transcript[classCnt].Hrs, vHrs);
Hrs from your struct is just a char type, and vHrs is an int type. You can simply assign it like:
Transcript[classCnt].Hrs = vHrs;
However, an int can hold a lot more data than a char can, this is going to give you a warning about overflow and you should listen to it (depending on the implementation char holds -128 to 127, where as int holds −2,147,483,648 to 2,147,483,647). Decide what data type you really wanted here and either make Hrs an int or vHrs a char then just do the assignment.
Second problem:
scanf("%c", vGrade);
vGrade as a character array (it is made up of more than one character) that means you should assign it with the string format operator "%s", but when you do a string you should make the array long enough for the number of characters you want + 1 (for the NULL terminator).
Third problem:
strcpy(Transcript[classCnt].Grade, vGrade);
Grade is a char whereas vGrade is an array. Again, you have to make a decision of type, if you wanted a "string" of characters then you need to make them both arrays, if you wanted just a single character then change the type of vGrade and do a simple assignment with the = operator.
The thing you're running into here is a data typing error.
The structure member .Hrs is of type "char". The argument to strcpy is a "char *". Think of it like this: A char is a single 8 byte number representing a value in ASCII. A "char *" is a pointer to an array of characters (or a string in C language).
The Above is traditionally true,but , today it might be a unicode or multi-byte character string, as well. In either case, what you need is the assignment operator (=), not a strcpy.
So you're telling strcpy to look at a single value (char), not a string of values (char *) which is it expecting as it's argument. In this case, you can just copy the value of the integer you scanned in with scanf directly.
Transcript[classCnt].Hrs = vHrs;
and
Transcript[classCnt].Grade = vGrade;
If you're looking for the best book ever written, well in my opinion anyway :-), on C Language, check out:
C Programming Language (2nd Edition) - Looks like it's available on Amazon (or at you're favorite used book seller) for about $21 (USD).

Resources