Wrong int outputted? - c

#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.

Related

Can I make a while loop using Char, instead of Double?

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

Does specifying array size for a user input string in C matter?

I am writing a code to take a user's input from the terminal as a string. I've read online that the correct way to instantiate a string in C is to use an array of characters. My question is if I instantiate an array of size [10], is that 10 indexes? 10 bits? 10 bytes? See the code below:
#include <stdio.h>
int main(int argc, char **argv){
char str[10] = "Jessica";
scanf("%s", &str);
printf("%c\n", str[15]);
}
In this example "str" is initialized to size 10 and I am able to to print out str[15] assuming that when the user inputs a a string it goes up to that index.
My questions are:
Does the size of the "str" array increase after taking a value from scanf?
At what amount of string characters will my original array have overflow?
.
When you declare an array of char as you have done:
char str[10] = "Jessica";
then you are telling the compiler that the array will hold up to 10 values of the type char (generally - maybe even always - this is an 8-bit character). When you then try to access a 'member' of that array with an index that goes beyond the allocated size, you will get what is known as Undefined Behaviour, which means that absolutely anything may happen: your program may crash; you may get what looks like a 'sensible' value; you may find that your hard disk is entirely erased! The behaviour is undefined. So, make sure you stick within the limits you set in the declaration: for str[n] in your case, the behaviour is undefined if n < 0 or n > 9 (array indexes start at ZERO). Your code:
printf("%c\n", str[15]);
does just what I have described - it goes beyond the 'bounds' of your str array and, thus, will cause the described undefined behaviour (UB).
Also, your scanf("%s", &str); may also cause such UB, if the user enters a string of characters longer than 9 (one must be reserved for a terminating nul character)! You can prevent this by telling the scanf function to accept a maximum number of characters:
scanf("%9s", str);
where the integer given after the % is the maximum input length allowed (anything after this will be ignored). Also, as str is defined as an array, then you don't need the explicit "address of" operator (&) in scanf - it is already there, as an array reference decays to a pointer!
Hope this helps! Feel free to ask for further clarification and/or explanation.
One of C's funny little foibles is that in almost all cases it does not check to make sure you are not overflowing your arrays.
It's your job to make sure you don't access outside the bounds of your arrays, and if you accidentally do, almost anything can happen. (Formally, it's undefined behavior.)
About the only thing that can't happen is that you get a nice error message
Error: array out-of-bounds access at line 23
(Well, theoretically that could happen, but in practice, virtually no C implementation checks for array bounds violations or issues messages like that.)
See also this answer to a similar question.
An array declares the given number of whatever you are declaring. So in the case of:
char str[10]
You are declaring an array of ten chars.
Does the size of the "str" array increase after taking a value from scanf?
No, the size does not change.
At what amount of string characters will my original array have overflow?
An array of 10 chars will hold nine characters and the null terminator. So, technically, it limits the string to nine characters.
printf("%c\n", str[15]);
This code references the 16th character in your array. Because your array only holds ten characters, you are accessing memory outside of the array. It's anyone's guess as to if your program even owns that memory and, if it does, you are referencing memory that is part of another variable. This is a recipe for disaster.

how to read a string

I´m new to programming and I'm still trying to figure out how everything works out but I want to write a string what should be used later on with adding characters, split the text, upper/lower cases and so on. Right now I am stuck on the reading part of the string and this is what I have so far:
int A, str[100];
printf("Write the text you want to use:\n");
char A;
scanf("%c", &A);
When I run the program it just jumps over this part, is it because I just wrote char A instead of str?
There are several things wrong. First of all you are declaring two times A, with two different types - you should get an error there because you can only declare a variable once.
Secondly, you should indeed store the string in str[100], as it is an array (which can store multiple variables, one in each element, therefore 100 in your case). You should also use char arrays, not int. A is also useless in your case because you will store the string in str.
It is better to use fgets for strings, because it is more secure. Also, scanf will stop reading after the first space in your string, which in most cases is not what you want.
This should work, I also added explanations:
printf("Write the text you want to use:\n");
char str[100];
fgets(str,100,stdin); // 100 is the number of characters to store, stdin indicates that you are reading from the standard input, what the user is typing
printf("String: %s",str); // just for verification
Firstly, You have declared the variable "A" first as an integer, and later as a character datatype, this will generate a conflict during compilation. This can be rectified by using different variable names for both.
After that, answer to your problems can be-
Strings are stored as an array of characters of arrays in C, not just by a single char. So you should declare the desired variable to obtain the string from the user as variable_name char[100] and then use this in fgets.
eg:
printf("Enter the input text:\n");
char string[50];
fgets(str,100,stdin); // the max length of string that can be taken is depicted by 50.
printf("Input was: %s",string); // check your string variable contents, mind the %s used to mark string variables in C
You can use the string library of C, which has a lot of advanced functionalities with an easy and simplified syntax. Go through the link, you'll find it much easier than anything else

Why can i not use %s instead of %c?

The whole function the question is about is about giving a two dimensional array initialized with {0} as output and making a user able to move a 1 over the field with
char wasd;
scanf("%c", &wasd);
(the function to move by changing the value of the variable wasd is not important i think)
now my question is why using
scanf("%s", &wasd);
does only work partly(sometimes the 1 keeps being at a field and appears a 2nd time at the new place though it actually should be deleted)
and
scanf("%.1s", &wasd);
leads to the field being printed out without stop until closing the execution program. I came up with using %.1s after researching the difference between %c and %s here Why does C's printf format string have both %c and %s?? If one can figure out the answer by reading through that, i am not clever or far enough with c learning to get it.
I also found this fscanf() in C - difference between %s and %c but i do not know anything about EOF which one answer says is the cause of the problem so i would prefer getting an answer without it.
Thank you for an answer
Simple as that, %s is the conversion for a (non-empty) string. A string in C always ends with a 0 byte, so any non-empty string needs at least two bytes. If you pass a pointer to a single char variable, scanf() will just overwrite whatever is in memory after that variable -- you cause undefined behavior and anything can happen.
Side note, scanf("%s", ..), even if you give it an array of char, will always overflow the buffer if something longer is entered, therefore causing undefined behavior. You have to include a field width like
char str[10];
scanf("%9s", str);
Best is not to use scanf() at all. For your single character input, you can just use getchar() (be aware it returns an int). You might also want to read my beginners' guide away from scanf.
A char variable can hold only one byte of memory to hold a single character. But a string (array of characters) is different from a char variable as it is always ended with a null character \0 or numeric 0. So in scanf you specifically mentioned whether you are reading a character or a string so that scanf can add a null character at the end of a string. So you are not suppose to use a %s to read a value for a char variable

Asking for a name and returning the length of the name in C

I've been struggling with this code for quite some time now.
This is my first time posting here. I am new to C, and I feel that I almost got it.
I have to ask for your name, middle initial, and last name. Then I greet you and tell you the length of your name. Sounds simple enough. I have the following code, I have to use the header file as it is here and that makes things worse. Any help would be greatly appreciated, I feel that I already applied all my knowledge to it and still can't get it to work.
This is my header file:
#ifndef NAME_H_
#define NAME_H_
struct name{
char first[20];
char middle;
char last[20];
};
#endif
and this is my .c file:
#include "name.h"
#include <stdio.h>
#define nl printf("\n");
int strlen(char*s);
char first;
char middle;
char last;
main()
{
printf("enter your first name : ");
scanf("%c", &first);
printf("\n enter your middle initial name : ");
scanf("%c", &middle);
printf("\n enter your last name: ");
scanf("%c", &last);
printf("\n\n Hello %c",first, " %c" ,middle, " %c", last);
printf("\n The String returned the following length: ",strlen);
}
I have t use printf and scanf, then store the name components a name "structure" imported from name.h and lastly use int strlen(char *s); to calculate it.
I get this output with the weird indentation and everything:
enter your first name : Joe
enter your middle initial name :
enter your last name:
Hello J
The String returned the following length: [-my user id]$
Thanks!
Several things about this are not quite right.
First, you shouldn't be declaring strlen yourself. It's a standard C library function, which means you should include the appropriate header. In this case,
#include <string.h>
Second, you're storing the input in variables of type char. Those are literally what they say: they store a single character. So unless you're only allowing people to have single-character names, you need a bit more than that. This sort of string input problem is actually rather tricky in C, since you have to do explicit memory management and don't know how much data the user is going to send you in advance. One of the simpler things is to just use a large buffer and truncate, but for a more complex program you'd want to do error handling and possibly dynamically resize the buffer. But for starters:
char first[1024];
char middle[1024];
char last[1024];
will at least get you started. Your struct name has some of this, but you're not currently using it (and the sizes are pretty small).
Next, scanf is a tricky way to get input strings. scanf of a %s pattern will happily read more than 1024 characters and write over the end of the buffer and destroy your program. This is why C programmers usually read input data using fgets instead, since then you can more easily say how big of a buffer you're willing to read:
fgets(first, sizeof(first), stdin);
Be aware that if the user enters more than 1023 characters, it will read the first 1023 characters and then leave the rest there, where you'll end up reading it as part of the middle name. String handling in C is complex! C is not good at this sort of thing; that's why people tend to use Perl or similar languages for this sort of interactive string handling where you don't know sizes in advance. In C, you have to pursue a strategy like repeatedly calling fgets until you get a newline at the end of the result and then deciding whether to dynamically resize your data structure or throw an error. Alternately, you can use scanf with %1023s but you need to qualify the format to specify the maximum length. The syntax is a bit weird and tricky; fgets is simpler when you're reading character strings.
As mentioned in the other answer, strlen is a function that you need to call on a char * variable (or char array) to get the length of the string it holds. You probably want to call it on first, middle, and last and add them together.
Finally, in your last printf, you have to pass one format and then all of the arguments for that format. You want something more like:
printf("\n\n Hello %s %s %s", first, middle, last);
(once you fix the type of those variables).
This is a lot of random detail. I hope it helps some. The important brief takeaway is that a string in C is a sequence of char ending in a char with a value of 0, and all C data structures have to be sized in advance (either statically or dynamically with malloc). C furthermore has no bounds checking, so it's completely up to you to ensure that you only read as much data as you created space for.
use
strlen(first)
to get the length of variable first ..similarly for other varibles... To get the cumulative length use
printf("\n Length: ",strlen(first)+strlen(middle)+strlen(last));

Resources