I'm trying to make a simple program from C to store a data then save it to 2d array there's 2 data stored in the 2d array. I think the saving code is work well, but when I try to print out the data stored in 2d array it crashes.
Here's my code :
#include <stdio.h>
int main(){
char data[2][3];
//input the data then save it in 2d array
printf("enter the first word: ");
scanf("%s", &data[0][0]);
printf("enter the second word: ");
scanf("%s", &data[1][0]);
//here is the problem when iam trying to print out the stored data in 2d array
printf("first word: %s\nsecond word: %s", data[0][0],data[1][0]);
}
You have 3 issues with your code.
First, and the one causing your code to crash is your final printf(). You passed in data[0][0] which is of type char to %s which takes a null terminated string. You have also need an extra new line at the end. Change it to:
printf("first word: %s\nsecond word: %s\n", data[0], data[1]);
Second, your second dimension of your array is only 3. This means you can only store strings of size 3 or less. Accounting for the null terminator at the end, it's just a 2 character array. Change the second dimension to a bigger number (i.e. data[2][50]).
Third, &data[0][0] is redundant. You are dereferencing a pointer then making it a pointer again. Just do data[0] and data[1] in your scanf().
About your confusion of 2d char arrays
I think you are confused about what char arrays are and what c-strings are. A char array is an array of char. "Bill", for example, would be a char array where 'B' will be the index 0, 'l' will be index 3, and a null ternimator '\0' will be the last index to tell the machine that this is the end of the string.
A 2d char array would be an array of those strings (e.g. "Bill") like "Bill", "Bob", "Alice" etc. If you want to also keep track of not only people's names, but also their addresses, phones etc, you might need a 3d array.
The 3d array will look something like data[2][4][50]. Where the first level are the people you want to keep track of. The second level are the attribute of a specific person (name, address etc.). Third level will be an array of characters (char) that makes up an attribute about a person.
Clearing one thing...
Pass the address of a character array not the address of a char.
scanf("%s", data[1]);// same as &data[1][0]
Here you will see that the passing the address of the char variable also works because it is basically coincides with the address of the char array.
Error lies somewhere else...
Also you should pass the address of the char array to the printf.
printf("first word: %s\nsecond word: %s\n", data[0], data[1]);
Or as it is pointed out in the line before..yes you got it right..this also works
printf("first word: %s\nsecond word: %s\n", &data[0][0], &data[1][0]);
And as you know there will be 2 characters use scanf("%2s",data[1]).
So where did I do wrong?
"%s" expects a char* and what you passed to it is char. That's why it ran into error. Yes, it considered that char value to be an address and tried to access it and it invoked undefined behavior.
If you want to print characters then you will use different format specifier:
printf("%c",data[1][0]);
Few things to point out:-
You are only considering 2 length char arrays or 2 length strings.
To remind you once more %c deals with arguments of type char and %s deals with arguments of type char*. (That's why the distinction in printf).
scanf() is like a parser. In case it fails to parse something it skips it. There are better ways to get input fgets() etc.
Related
I'm new to this, and I'm assuming there is an easy solution to my issue. My first formula works exactly how I'd like it to. If the user input matches dogage99, then it prints "Correct". I want to do something similar, but using words instead of numbers. I've switched double for char, and adjusted the formula accordingly.
The problem is, the second formula doesn't work as I expected. When the user input matches dogname1, it doesn't print "Correct", it just continuously asks to "enter dog name".
What can I do to fix my issue?
int main()
{
double guess99;
double dogage99 = 3;
while (guess99 != dogage99) {
printf ("enter dog age:");
scanf ("%lf", &guess99);
}
printf ("Correct\n");
char guess1;
char dogname1= "spot";
while (guess1 != dogname1) {
printf ("enter dog name:");
scanf ("%s", &dogname1);
}
printf ("Correct\n");
First of all the line
char dogname1= "spot";
should be corrected to
char *dogname1= "spot";
This way the char array dogname1 will be correctly initialized as a character array and will contain the null-terminator "\0" at the end of the array.
You must also ensure, that guess has enough memory secured, so you must either create a array of sufficiently enough bytes (for e.g. 256), or dynamically allocate memory. In this example I would do the first changing char guess1; to char guess1[256];
Knowing that guess1 has sufficiently enough memory and a null-terminator we can next rewrite the while loop to
while(strcmp(guess1, dogname1)) { ... }
The strcmp() standard library function returns 0 if and only if both character arrays match lexicographical and that is also the time we want to go out of the loop. It is also important to know, that you must ensure both arrays have null-terminators when using this exact function. If you cannot ensure it, then use strncmp().
For reference about all the different compare functions and their implications: https://www.ibm.com/docs/en/aix/7.1?topic=s-strcmp-strncmp-strcasecmp-strcasecmp-l-strncasecmp-strncasecmp-l-strcoll-strcoll-l-subroutine
I am sure the compiler is complaining big time at you about
char dogname = "spot";
in c the type char represent a single character not a string. Strings in C are a sequnce of characters followed by a char set to \0. The compiler will set that up for you if you do
char *dogname="spot";
It will allocate 5 bytes , load s,p,o,t,\0 into those bytes and set the dogname variable to point at the first character.
If you want to compare string you have to use the c library function called strcmp - https://man7.org/linux/man-pages/man3/strcmp.3.html.
Alos you need a char array to receive the input. We just say we want 50 characters. Must also tell scanf to not allow more than 50 charaters. Note that I asked for 51 character array to allow for the trailing 0 that must always be present.
so your loop becomes
char guess1[51];
char *dogname1= "spot";
while (guess1 != dogname1) {
printf ("enter dog name:");
scanf ("%50s", guess1);
}
printf ("Correct\n");
note you must #include string.h
check this out https://www.tutorialspoint.com/cprogramming/c_strings.htm
#include <stdio.h>
int main(){
int age;
char name[] ="";
printf("enter your age: ");
scanf("%d", &age);
printf("enter your name: ");
scanf("%s", &name);
printf("your name is %s and you are %d years old.",name, age);
return 0;
}
If i for example set the age to "20" and the name to "name", it outputs the following:
your name is name and you are 6647137 years old.
Why does it say "6647137" years instead of 20?
char name[] ="";
You do not define name correctly.
#define MAX_NAME_LENGTH 100
char name[MAX_NAME_LENGTH+1];
Defining it incomplete and completing it afterwards you make it point to some region where there may be other variables aound the array defining the string literal, or the string literal can be even in RO memory, making it impossible to write. It is undefined behavior trying to write at the pointer of a string literal (6.4.5.p6 String literals, page 63).
You overwrite beyond the much too short array of chars for name.
It currently is of size 1, holding exactly only the teminating '\0'.
Your weird age value can in many environment be explained by the integer being the first victim.
Make sure to use an array of sufficient size.
Also it is very much recommended to use advanced features of scanf() to avoid buffer overrun.
Please read the documentation:
https://en.cppreference.com/w/c/io/fscanf
And this article might be very helpful:
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
Learn this soon and learn this well: C does not have a first-class "string" type!
When you wrote
char name[] = "";
you did not declare a string variable, that initially contained an empty string, but that could and would automatically expand to contain any string you tried to assign to it.
No, what you got was an array of char of size exactly 1, initially containing the empty string, consisting of exactly (and only) the string-terminating character '\0'. This array can't be used for much of anything: the only thing it's ever going to be able to contain is the empty string, because it doesn't (and will never) have room for anything more.
In C, it is generally your responsibility to know how big your strings are going to be, and to explicitly allocate each variable to refer to enough memory for any string it might contain.
For example, you could write
char name[11] = "";
Now what you're saying is, "Give me an array of characters, sufficient to contain strings up to 10 characters long (plus 1 for the terminating \0 character), initially containing the empty string."
Now you can safely say
scanf("%s", name);
But there are two more points to make.
First, you'll notice that I have left out the &. You might have gotten the impression that you always need the & on your variables when you call scanf. And that's a real rule, but it has an exception: it turns out that you do not need the & when you're using %s to read a string into an array. Sometimes the error is innocuous (the code will happen to work anyway), but sometimes it will cause problems (such as when you use %s to read into an array pointed to by a pointer variable). My compiler warns me warning: format specifies type 'char *' but the argument has type 'char (*)[1]' when I do something like this.
But second, if we've declared
char name[11] = "";
, then how do we actually enforce that? How do we arrange that we, or a function like scanf over which we have less control, won't accidentally try to write more than 10 characters to our name array?
As we've already seen, if you just call
scanf("%s", name);
you don't get any protection. scanf will read as many characters as the user types, until it sees a newline or other whitespace, and it will write all those characters to the variable you provided, and if that's more characters than the variable can hold, boom, something bad happens.
One way of protecting against this is to give scanf a limit on the number of characters it can read:
scanf("%10s", name);
Now, by putting that 10 in there, you're telling scanf not to read a string longer than 10 characters, so it won't overflow your name array.
I'm trying to read the characters of a character array by number in c. I've stripped the program down to isolate the problem. I know this is about my misunderstanding of how arrays and memory works and I am ready to be called clueless but I would like to know what I am misunderstanding here. Here is what I have:
#include <stdio.h>
int main(int argc, char **argv) {
char buffer[] = "stuff";
printf("buffer is %s\n", buffer);
printf("first character of buffer is %s", (char)buffer[0]);
return 0;
}
You have to write the correct format specifier. Now you used %s ...what happens?
It looks for an string which is null terminated. But it doesn't find one. So it simply cant put anything in the output . That's it.
Use %c instead.
In C there is a very big difference between a character and a string.
A character is simply a number in a range of 256 different options.
A string is not really a type of its own, it is merely an array of chars (which, in C, is simply evaluated as a pointer to the first character of the string).
Now, when you type buffer[0], this is evaluated to the value at the beginning of the string (first value in the array). Indeed, this is of char type (and therefore you do not need the (char) casting, because this will not do anything in the case of your code).
What you need is to tell printf() how to evaluate the input that you give it. %s is for a string (an array of chars). But note and remember that buffer[0] is not an array of chars, but rather a char.
So you actually want to use %c, instead of %s. This tells printf() to evaluate the parameter as a char type.
What your code currently does is take the value buffer[0] (which is just a number) and consider it as a pointer to a location in memory where a string is kept, and printf() tries to print this string. But this memory location is simply invalid. It is not a location you've accessed before.
In conclusion you want:
printf("first character of buffer is %c", (char)buffer[0]);
or even simpler:
printf("first character of buffer is %c", buffer[0]);
For other specifiers of the printf() function, look here:
http://www.tutorialspoint.com/c_standard_library/c_function_printf.htm
If you want to print only a single char use %c format.
printf("first character of buffer is %c\n", (char)buffer[0]);
I'm getting confused while trying to make the tic tac toe game in c. I'm following a book that uses a single char array of 8 elements to create the board. I know an array[8] contains 9 elements, but if the array is declared as char array, since it has to contain spaces to make the empty board for the game, shouldn't it be array[9], since it has to contain the 9 characters plus a null character '\0'? I'm having the same doubt when converting the board to a 2d array, since I understand the board should be made with an array[3][3], but if I want to declare it as char, where is the place for the null character?
An array of characters can hold any value in any position. It's only when you want to use certain functions that you need to make sure that there's a NUL character (that's a 0, not a '0'!) at the end of the string - that tells the function when to stop processing!
So: char john[4] = { 'J', 'o', 'h', 'n' }; is perfectly legal - just don't pass john to strlen(), since it will keep counting until it finds a 0 value, and there aren't any in the array!
Also: char tictactoe[3][3]; doesn't need a 0 anywhere - unless you try to pass the whole array to printf() for some reason...
Note that you can safely do the following:
printf(" %c | %c | %c \n", tictactoe[0][0], tictactoe[0][1], tictactoe[0][2]);
printf("---+---+---\n");
printf(" %c | %c | %c \n", tictactoe[1][0], tictactoe[1][1], tictactoe[1][2]);
printf("---+---+---\n");
printf(" %c | %c | %c \n", tictactoe[2][0], tictactoe[2][1], tictactoe[2][2]);
because using %c means "print one character", not "print a string of characters".
The form of a string that ends in a NUL is often called an ASCIIZ (ASCII-Zeroed) string, and is the reason why a nine-char array can only hold an eight-character string (the opposite of what you said) - it needs the ninth to hold the NUL.
And, as always in C, any array goes from 0 to length-1, hence the [0], [1] and [2] in my example
The terminating zero is needed if a character array is used to store strings.
In the case of your task there is no need to store strings in the array.
So in C you may declare for example a 3*3 array the following way
char board[3][3] =
{
" ", // three spaces
" ",
" "
};
Each element of the array will not contain the terminating zero though it is initialized by a string literal.
On the other hand you can include the terminating zero in each element if you think that it will be simpler to output such an array. In this case the array should be defined like
char board[3][4] =
// ^^^
{
" ", // three spaces
" ",
" "
};
As for your statement that
an array[8] contains 9 elements
then the array is declared as having exactly eight elements. :)
I think you mean string literals. For example string literal "Hi" in C has type char[3] due to the terminating zero that is stored in the literal.
2D arrays are essentially 1D arrays with added ease of use for the programmer. The book you read probably just stores the values at cells, and displays them instead of a chunk of characters as string, like you said. This is a bit more efficient than storing the entire board as string.
Suppose you want to store a 2D array of 4x4 area. You can represent it as a 1D array of size 16, and access indicies like so:
arr[j + i * 4]
Where j is where you are in that 4 unit block, and i is what 4 unit block you are in.
Also, an array of size [8] has 8 elements. Ex:
char arr[8]; // has 8 elements, not 9
I know an array[8] contains 9 elements
No, why it should be? An array, defined like int arry[8] contains 8 elements only. That too, in C, array indexing is 0 based, means, for an array as above, only array[0] to array[7] will be valid access.
That said, for a char array, is to be used as string, should have the space for a null-terminator, too. So, if you want to have a char array of 9 elements and want to use it as a string, you need to define it as char[10].
Using a character as the value of an array has nothing to do with the fact that an array of char can decay to a pointer char* and be interpreted as a NUL terminated string.
A string doesn't have a specific type in C, it's just a way to interpret some data. So you are mixing two concepts.
A char array doesn't have to be NUL terminated, it requires NUL termination if you are going to use it with functions which will use the data as a string.
Having a char board[3][3] is perfectly legal and has room for 9 char elements, it doesn't require \0 since you are not going to use that data as a string.
i have a given Input of four scanf-strings which i want to save in a multidimensional array. I Don't know if i save the string right, but i can't just simply print the whole array or certain characters of it.
char getr[4][4];
for (z=0; z<4; z++){
scanf(" %99s", &getr[z]);
}
for (s=0; s<4; s++) {
printf("%s\n",getr[s]);
}
Input:
abcd
efgh
ijkl
mnop
Output:
abcdefghijklmnop
efghijklmnop
ijklmnop
mnop
what if i just want to print the second line or the fourth character of the first line? Does anybody know?
First, change as following:
scanf(" %99s", getr[z]); //getr[z] is the address to take the 4 characters string
To print out the second line:
printf("%s\n", getr[1]);
To print out the fourth character of the first line:
printf("%c\n", getr[0][3]); // %c is used here because just print one character.
To store 4-char strings, like your example input, you need 5-char arrays to leave room for the terminating null character:
char getr[4][5];
Your scanf() format string should also reflect the amount of space you have; %99s could read up to 100 bytes (99 chars plus the null), and you only have 5 (including the null, after the above change). Also, &getr[z] and getr[z] happen to give the same address, but the types of the pointers are different -- but getr[z] gives a char * which is appropriate in this case. So...
scanf(" %4s", getr[z]);
Those changes will already keep the strings from running together, so individual strings can be accessed as getr[0] through getr[3]. To print individual characters within a string, add an additional set of indexing brackets and use a function that prints a character rather than a string:
fputc(getr[0][2],stdout); /* print 3rd char in 1st string */
printf("%c",getr[1][3]); /* print 4th char of 2nd string */
The reason you were getting all your strings concatenated was because the null char from the earlier strings overflowed into the next char array, and was overwritten by the first char of the next string you read. The last string's null would have overflowed past your whole 2D array into whatever was next in memory (which is bad).