i am starting to learn C and I have ran into the problem of adding a string input to a 2D array, i am able to get the string input correctly but when i try and add the string element to the array it is not working as expected.When printing the array(which is how i test the program) it will assign each index in the array a single character instead of the entire string.
And here is my code for viewing, thank you very much in advance i appreciate any help that is posted.
#include <stdio.h>
main()
{
char c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
}
The output looks as follows with the sample input 'Penelope!'
c_array[0][0]=P
c_array[0][1]=e
c_array[0][2]=n
c_array[1][0]=e
c_array[1][1]=l
c_array[1][2]=o
c_array[2][0]=p
c_array[2][1]=e
c_array[2][2]=!
When you declare:
char c_array[3][3];
This means that each element of your 2D array is a "char" (a single character); not a "string of characters".
To have each element be a string of characters, you need to declare your array in the following way:
char string_array[3][3][256];
I am not sure this is what you want to do though. Mw feeling is that you want an array of 3 elements where each element is a string. In that case, [3] is hardly enough, your strings will have to be less than two characters (the third being reserved for the terminating zero).
Strings aren't a type. They're a value pattern, like if you say an int stores a multiple of ten, then it ends in 0... If you say an array of char stores a string, then it ends at the first '\0', see? We can store multiples of ten in different kinds of integer variables, and likewise for strings.
Strings are patterns of values, not types. When choosing which integer type we want to use, we consider the range for integers. We choose int for small integer values (less than 32768), long for larger values (less than 2147483648) or long long for values larger than that. As a result, we choose the correct type of integer depending on the multiple of ten we expect. Likewise for strings, we need to make sure we have enough memory for the characters in the string followed by the '\0' at the end.
The character &c_array[x][y] only has enough memory for 0 characters followed by a '\0' at the end; it's only useful for storing an empty string. Perhaps you meant to declare c_array like this:
char c_array[3][3][256];
In this case, scanf expects %s to correspond to an argument of the type char *... but as your compiler will probably warn you, &c_array[x][y] will have the type char (*)[256]. If you want to fix that warning, you'll need to remove the & from your scanf code:
if (scanf("%s", c_array[x][y]) != 1) {
/* XXX: Handle an error here, *
* e.g. by exiting or returning or something */
}
While we're on that topic, you'll notice that I removed the redundant space; %s already performs the functionality that the format directive would perform. I also wrote code to check the return value of scanf, as you should...
Remember how we spoke about choosing the types of integers that we use to store data? One other consideration is whether or not the data we intend to store can be negative. Consider this: In your code, should x and y be able to store negative values? What sense does a negative array index make? It is advisable that all array indexes be declared as size_t. When you use printf to print a size_t value, you'll want to use the %zu format specifier rather than %d.
char c_name[256];
/* ... */
printf("The string is %s\n",c_name);
Now, if the string is stored into c_array[x][y], then what is the point of c_name? That's an unnecessary variable. Use c_array[x][y], instead.
printf("\nPlease enter a name to the system:");
Common implementations will often refrain from printing characters until a '\n' is written; the line is printed all at once rather than character by character. As a result, you might see some strange behaviour such as this line not appearing at the right time. Fix this problem by putting the '\n' on the end of the line, rather than the beginning:
printf("Please enter a name to the system:\n");
... or use puts, which adds a '\n' for you automatically:
puts("Please enter a name to the system:");
... or use fflush, which will write all pending unwritten data even if there is no '\n':
fflush(stdout);
In your code
scanf(" %s",&c_array[x][y]);
printf("The string is %s\n",c_name);
both the statements are wrong.
%s expects a pointer to an array, not a single char. To scan a single char, you need %c format specifier.
c_name, as used in the printf() is uninitialised. Using uninitialised value invokes undefined behaviour.
Solution: To take input element by element, you can do do something like
for(x=0; x<=2 ;x++)
{
printf("Start entering the name, one character at a time\n");
for(y=0; y< 2; y++) //note only '<' here
{
scanf(" %c", &c_array[x][y]); // note the leading space
}
c_array[x][y] = 0; //null termination of array to be used as string
}
If you want to assign a string to each index in the array, then create the array as follows :
#include<stdio.h>
int main(void)
{
char a[2][10];
int i=0;
char temp[20];
for(i=0;i<2;i++)
{
scanf("%s",temp);
strcpy(a[i],temp);
}
printf("%s",a[0]);
return 0;
}
Each string that you enter will be stored in each index of the array.
#include <stdio.h>
#include <string.h>
int main(void){
char c_array[3][3];
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
printf("\nPlease enter a name to the system:");
scanf("%255s",c_name);
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
if(i_user_input==1)
;
else if(i_user_input==2){
memcpy(c_array, c_name, sizeof(c_array));
for(x=0;x<3;x++){
for(y=0;y<3;y++){
printf("c_array[%d][%d]=%c\n", x, y, c_array[x][y]);
}
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3
int main(void){
char *c_array[SIZE][SIZE] = { NULL };
int x;
int y;
//int z=10;//unused
int i_user_input;
char c_name[256];
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
printf("\nPlease enter a name to the system:");
scanf("%255s", c_name);
printf("The string is %s\n", c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d", &i_user_input);
c_array[x][y] = strdup(c_name);
if(i_user_input==1){
continue;
}
if(i_user_input==2){
int x, y;//local variable
for(x=0;x<SIZE;x++){
for(y=0;y<SIZE;y++){
if(c_array[x][y] != NULL)
printf("c_array[%d][%d]=%s\n", x, y, c_array[x][y]);
}
}
}
}
}
for(x=0;x<SIZE;x++)
for(y=0;y<SIZE;y++)
free(c_array[x][y]);
}
Why not use pointers in you array/matrix?
#include <stdio.h>
#include <string.h>
main()
{
char *c_array[3][3];
int x;
int y;
int z=10;
int i_user_input;
char c_name[256];
for(x=0;x<=+2;x++)
{
for(y=0;y<=2;y++)
{
printf("\nPlease enter a name to the system:");
scanf(" %s",c_name);
new_string = malloc(strlen(c_name)+1)
if (new_string == NULL) {
print("error allocating string\n")
exit(-1);
}
strcpy(new_string, c_name);
c_array[x][y] = new_string
printf("The string is %s\n",c_name);
printf("Please press '1' if you would like to keep entering names\n");
printf("Please press '2' if you would like to print the list of names:");
scanf("%d",&i_user_input);
if(i_user_input==1)
continue;
if(i_user_input==2)
for(x=0;x<=2;x++)
{
for(y=0;y<=2;y++)
{
printf("c_array[%d][%d]=%c\n",x,y,c_array[x][y]);
}
}
}
}
for(x=0;x<=2;x++) {
for(y=0;y<=2;y++) {
free(c_array[x][y])
}
}
}
The code above stores the input string in each cell of the array, if that is your goal.
Note: I have no tried it, so there may be subtle errors. My point is to show you how to use pointers and their equivalence to arrays. Using C without pointers is pointless. :)
Related
I created a struct datatype 'ans' that contains three string datatype member variables a[2],b[2],c[2]. Inside main, I created a struct variable 'p' to accept the three string inputs and then pass it to a function - void f1(ans *x) via call by reference to print the strings. Now in the function, instead of printing the three separate strings (*x).a,(*x).b,(*x).c, it is printing the whole string joined together. I am attaching the code and output for reference:
#include <stdio.h>
typedef struct
{
char a[2];
char b[2];
char c[2];
} ans;
void f1(ans *x) {
printf("The strings are :\n");
printf("%s\n",(*x).a);
printf("%s\n",(*x).b);
printf("%s\n",(*x).c);
}
int main() {
ans p;
printf("Enter for a:\n");
scanf("%s", p.a);
printf("Enter for b:\n");
scanf("%s", p.b);
printf("Enter for c:\n");
scanf("%s", p.c);
f1(&p);
return 0;
}
Sample output:
Enter for a:
ab
Enter for b:
cd
Enter for c:
ef
The strings are :
abcdef
cdef
ef
Can anyone explain why is this showing as output instead of the following:
The strings are:
ab
cd
ef
I can't figure out what's happening :(
In scanf("%s", p.a);, scanf reads characters and writes them to the memory pointed to by p.a. It also writes a terminating null character after them. Since the a member of the structure is declared as char a[2];, when scanf writes more than two characters, including the terminating null, the behavior is not defined by the C standard.
In printf("%s\n",(*x).a);, for %s, printf takes a pointer to a char and prints the characters it finds there until a terminating null character marks the end of the string. When there is no terminating null character the array that is (*x).a, printf overruns the array, and the behavior is not defined by the C standard.
To fix the problem, ensure there is enough space in the arrays for all the characters to be written into them, including the terminating null character, or ensure that no more characters are written in the arrays than will fit.
if you enter "ab", scanf will scan string as "ab\0" which is 3 characters, therefore your a[2] won't fit as same as other variabls.
To prevent scanf from overruns the array, a simple adaptation of your program, from the several that can be suggested:
#define MAXCH 3
typedef struct
{
char a[MAXCH];
char b[MAXCH];
char c[MAXCH];
} ans;
void f1(ans *x)
{
printf("The strings are :\n");
printf("%s\n",(*x).a);
printf("%s\n",(*x).b);
printf("%s\n",(*x).c);
}
int main()
{
ans p;
char in[128];
printf("Enter for a:\n");
scanf("%s",in);
snprintf(p.a,MAXCH,"%s",in);
printf("Enter for b:\n");
scanf("%s",in);
snprintf(p.b,MAXCH,"%s",in);
printf("Enter for c:\n");
scanf("%s",in);
snprintf(p.c,MAXCH,"%s",in);
f1(&p);
return 0;
}
Sample output:
Enter for a:
abcdefgh
Enter for b:
cdefghij
Enter for c:
efghijkl
The strings are :
ab
cd
ef
please take a look at the code below.
#include <stdio.h>
#include <conio.h>
struct str {
char st[1];
char rule[20];
} production_rules[30];
int main () {
int n;
printf("Enter number of productions: ");
scanf("%d", &n);
printf("Enter the productions\n");
for (int i = 0; i < n; i++) {
printf("Enter the non terminal: ");
scanf("%s", production_rules[i].st);
printf("Enter the RHS of the production Rule: ");
scanf("%s", production_rules[i].rule);
}
printf("the production rules are \n");
for (int i = 0; i < n; i++) {
printf("%s -> %s\n", production_rules[i].st, production_rules[i].rule);
}
return 0;
}
I am getting the following output
Enter number of productions: 1
Enter the productions
Enter the non terminal: A
Enter the RHS of the production Rule: abc
the production rules are
Aabc -> abc
Expected Output:
Enter number of productions: 1
Enter the productions
Enter the non terminal: A
Enter the RHS of the production Rule: abc
the production rules are
A -> abc
The problem is in the last line of the output. I don't understand why the char array is being concatenated. Can some one help me with this problem
There is no issue in your struct, but just the way you use printf, as you put %s to print the element "st", whilst you should use "%c" instead.
In fact, "st" is just a char[1], not a proper string, so it doesn't contain the string termination character '\0'.
As your struct is stored in memory as a buffer of consecutive char, the "%s" makes the "printf" stop when the termination string character is found, so at the end of the element "rule", and that's reason of your output.
So, just replace %s with %c when printf of st and it will work. Your code should appear like this:
for (int i = 0; i < n; i++) {
printf("%c -> %s\n", production_rules[i].st, production_rules[i].rule);
}
As mentioned in the comments, the problem was: not having a sufficient number of rooms in that character array. It is because the null-terminator character is always put at the end of the string, so it requires extra space.
In the current situation, your requirement is only a single character. So, you can change it into a char in the struct definition:
struct str {
char st;
char rule[20];
} production_rules[30];
And use it this way:
scanf(" %c", &production_rules[i].st);
Notice that an extra whitespace character is given here because it is necessary. Otherwise, it would simply ignore the input from being given.
Another method to solve this issue is to increase the length of the array by one. Suppose, you need 3 numbers as char[] then you need a length of 4 (extra one).
I must write a program in C that can print the middle letter of the string you entered. Spaces () are also calculated, and the number of characters must be odd.
Ex. Input
Hi sussie
--> 9 characters, including space
The output should be s.
I have tried this:
#include <stdio.h>
#include<string.h>
char x[100];
int main(void)
{
printf("Hello World\n");
scanf("%c\n",&x);
long int i = (strlen(x)-1)/2;
printf("the middle letter of the word is %c\n",x[i]);
return 0;
}
and the output always shows the first letter of the word I have entered.
You're only reading the first character from stdin (and incorrectly; you shouldn't be using &).
If you must use scanf, you should use this format:
scanf("%99[^\n]", x);
This is safe and doesn't read past the buffer.
Note that %s wouldn't work here. %s causes scanf to interpret whitespace as the end of the string.
A much better, safer, and easier solution would be to use fgets instead of scanf; fgets is safer and it doesn't require you to change a format string when you change the size of your array:
fgets(x, sizeof(x)-1, stdin);
This eliminates any possible issues with whitespace or buffer overflow.
int main()
{
char arr[1024];
char a;
int i,counter=0;
printf("enter string :: ");
fgets(arr,sizeof(arr),stdin);
for(i=0;i<strlen(arr);i++)
counter++;
for(i=0;i<strlen(arr);i++)
{
if(i==(counter/2))
printf("%c\n",arr[i]);
}
return 0;
}
#include<stdio.h>
#include<string.h>
void main()
{
int entry,i;
printf("\nPlease indicate the number of records you want to enter :\n");
scanf("%d",entry);
char ent[entry][100000];
printf("\nPlease input records of students (enter a new line after each record), with following format first name last name score \n");
for(i=0;i<entry;i++)
{
gets(ent[i]);
printf("%s",ent[i]);
}
}
The following is a code to accept data of student , first name last name and then score.
main should return int, not void.
int main(void) {
/* ... */
}
scanf("%d",entry);
scanf expects the argument corresponding to the "%d" format specifier to be an int *. Your argument, however, is an int. Perhaps you meant this:
scanf("%d",&entry);
On that note, you should really check the return value of scanf. For all you know, the user didn't enter anything numeric.
if (scanf("%d", &entry) != 1) {
exit(0);
}
In fact, this still allows the user to enter a negative number. Have you ever seen an array of a negative number of items? Seems strange to me, too... I think size_t would be a more appropriate type than int (and as a result, you'll need to use the %zu format specifier)...
Last but not least, gets is deprecated because it makes it impossible to prevent the user from overflowing buffers, which could cause segfaults.
#include <stdio.h>
#include <string.h>
int main(void)
{
size_t entry;
printf("\nPlease indicate the number of records you want to enter :\n");
if (scanf("%zu",&entry) != 1)
{
exit(0);
}
char ent[entry][100000];
printf("\nPlease input records of students (enter a new line after each record), with following format first name last name score \n");
for(size_t i=0; i<entry; i++)
{
fgets(ent[i], sizeof ent[i], stdin);
printf("%s",ent[i]);
}
}
you should use int main()instead of void main
when you use you should scanf("%d",&entry) instead of scanf("%d",entry),what scanf need is an address.
you shouldn't use gets(),it's dangerous,try fgets()
scanf("%d",entry); //scanf("%d",&entry)
char ent[entry][100000]; //error
you should use malloc to get an array when you can not know the length of an array in compiling time
The error is in scanf use scanf("%d",&entry) instead of scanf("%d",entry);
Suggestion: use int as return type for main
I am currently trying to solve a problem from CodeChef but I am having troubles with using fgets() inside a loop.
The first input (T) is going to be a positive integer containing the number of user inputs.
Then delimited by newline characters, the user is going to input a string below the length of 10 under any circumstances.
So, I've tried this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int T;
int diffX, diffY;
char s[SIZE];
scanf("%d", &T);
while (T--){
fgets(s, SIZE, stdin);
printf("%s\n", s);
}
return 0;
}
However, when I attempted to test the code with the following inputs:
3 Hello Hi What
I was only able to input until "Hi" then the program exited successfully (returning 0).
Why is this the case and how can I fix it?
Thank you in advance,
kpark.
fgets() consumes the newline left behind by the first call to scanf(). So, it is consuming 3 lines, but the first line looks like an empty line to the fgets() loop you have.
You can fix this by using fgets() to get the first line too, and parse the string into a number using sscanf().
fgets(s, SIZE, stdin);
sscanf(s, "%d", &T);
/* ... */
It is counting the read of the T as part of the counting. Add a newline in the scanf.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int T;
int diffX, diffY;
char s[SIZE];
scanf("%d\n", &T);
while (T--){
fgets(s, SIZE, stdin);
printf("%s\n", s);
}
return 0;
}
Is your Question is about how to read Multiple Strings in C ?
Then it can be done by 2 ways :-
1.By declaring two dimensional Array of characters.
//Let say we want 6 strings each of them having max 10 characters.
char set[6][10] ;
for(int i=0;i<6;i++)
scanf("%s",set[i])
2.By declaring one dimensional Array of pointers to character (Notice the naming Conventions), in which each of those pointer pointing to a String.
int main(){
int i,numOfStrings;
char temp[30];
printf("Enter Number of strings in set ");
scanf("%d",&numOfStrings);
//Here We have defined array of pointer that will store each string sepratly.
//Arry of pointer to character.
char *setOfStrings[numOfStrings];
for(i=0;i<numOfStrings;i++)
{
printf("Enter string ");
scanf("%s",temp);
setOfStrings[i]= (char*)malloc(sizeof(temp)); //allocted new memory and gave it to array of pointer
strcpy(setOfStrings[i],temp);
}
for(i=0;i<numOfStrings;i++)
{
printf("string = %s \n",setOfStrings[i]);
}
return 0;
}
But that need to understand :
In case of array of pointers we may initialize them with String but Can't take as input from Command line like
char *set[2]={"Dinesh","Kandpal"}; //Its valid but you can't do this from command line
for doing so What we do we will create an space dynamically ,store that address in the one of the element in 1-D array of pointers and then whatever value we have scanned copy that content to the another string to the location that we created using malloc