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
Related
hello ive got this simple program, where i need to imput a number, and 2-letter string, the string is working normally, but the number gets weird
here is the program
void main(){
int input_year=0;
char input_string[1];
scanf("%d %s", &input_year, input_string);
char temp1 = input_string[0];
char temp2 = input_string[1];
printf("%d", input_year);
printf("%c", temp1);
printf("%c", temp2);
}
input used: 20200405 RD number (whitespace) String
the temp1 and temp2 are ok, and do what i expect them to do, but the input_year prints 20200192 rather than 20200405.
You need to remember that strings in C are really called null-terminated strings. A string of even one single character need space for two characters to fit the null-terminator.
Also remember that the size provided in array declarations is the actual number of elements, not the top index. So when you define input_string as an array of a single element, that means it only have a single element, with index 0.
If you want to read a string containing two characters you need to define an array of three characters: The two characters in the string plus the null-terminator.
You also need to limit the number of characters that scanf will read, so users can't input arbitrarily long strings and cause buffer overflows.
In short:
// Place for two characters, plus null-terminator
char input_string[3];
// Limit the input to only two characters (not including null-terminator)
scanf("%d %2s", &input_year, input_string);
On another note, if you want to use the date input in any other way than a single number, I recommend you read it as separate year, month and day:
unsigned year, month, day;
char input_string[3];
scanf("%4u%u%2u %2s", &year, &month, &day, input_string);
Also note that I use unsigned as a type (and the corresponding scanf format) as the input can't and shouldn't be negative.
You should also really check what scanf returns, to make sure the input is valid.
And lastly, to better handle input validation, I recommend you use fgets to read the input into a large string. Then use e.g. sscanf (with checking return values) to attempt to parse the input.
Your input buffer is too small
char input_string[1];
That reserves space for one character. You need 3 in your case of 'rd'. The extra one is because c always adds a 0 at the end of a string. So you need
char input_string[3];
at least if you are sure its always 2 characters
Or maybe
char input_string[10];
if it could be larger. You can tell sprintf the max size you will accept like this (say 2 in your case)
scanf("%d %2s", &input_year, input_string);
-----------^
This is the code I have written.
#include<stdio.h>
int main()
{
char playerName;
int gameScores [10]= {12,5,21,15,32,10};
int totalPoints=0;
int x;
float avg;
for (playerName='A'; playerName<='Z'; playerName=playerName+1)
{
print("%c",playerName);
scanf ("/%s",playerName[x]);
}
putchar('\n');
for(x=6; x<10; x++)
{
printf ("What did the player score in game %d?". x+1);
scanf ("%d", &gameScores [x]);
}
for(x=0; x<10; x++)
{
totalPoints +=gamesScores[x];
}
avg=((float) totalPoints/10);
printf("\n\nThe Play's scoring average is %.1f.\n", avg);
return (0)
}
I am running into problems around line 22 with
scanf("/%s",playerName [x]);
it keeps coming up with an error. It says that the subscripted value is not an array, pointer, or vector. I would like it to list the player's name before the score average. Without the scanf if just gives me the alphabet above the input not a players name.
char playerName is just a single char, one byte. C strings are arrays of char, terminated by a zero (NUL) character. The single character treated as a string could therefore only hold the terminating NUL, and nothing else, i.e., it can only be the empty string.
You need to define playerName as an array large enough to hold the name + the terminating NUL, e.g.,:
#define MAX_NAME_LENGTH 100
char playerName[MAX_NAME_LENGTH + 1];
This would suffice for a single name, but since you have multiple players, you need an array of these arrays, e.g.:
#define MAX_PLAYERS 10
#define MAX_NAME_LENGTH 100
char playerName[MAX_PLAYERS][MAX_NAME_LENGTH + 1];
(You can also allocate the memory dynamically, such as with malloc, but that's outside the scope of the question.)
Also, your scanf has an extra slash / in the format string, which causes it to fail unless each player name is preceded by a slash in the input, which I'm guessing is not the case. Maybe you were going for the backslash \ to escape the %, but that is also not required here since the percent sign is only "special" in the printf/scanf format strings, not in C itself.
In a proper program you also need to guard against buffer overflow when reading with scanf. And should check the return value of scanf to verify that the input was successfully read (and perhaps retry or abort the program if not). See the documentation of scanf (and every other function you use) for the return values and arguments.
(Overall I would suggest learning to read lines into a buffer with fgets, as it may often be hard to recover from scanf errors in a sensible way, especially when the format strings become more complicated.)
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
So I'm writing a small program (I'm new to C, coming from C++), and I want to take in a string of maximum length ten.
I declare a character array as
#define SYMBOL_MAX_LEN 10 //Maximum length a symbol can be from the user (NOT including null character)
.
.
.
char symbol[SYMBOL_MAX_LEN + 1]; //Holds the symbol given by the user (+1 for null character)
So why is it when I use:
scanf("%s", symbol); //Take in a symbol given by the user as a string
I am able to type '01234567890', and the program will still store the entire value?
My questions are:
Does scanf not prevent values from being recorded in the adjacent
blocks of memory after symbol?
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
You can limit the number of characters scanf() will read as so:
#include <stdio.h>
int main(void) {
char buffer[4];
scanf("%3s", buffer);
printf("%s\n", buffer);
return 0;
}
Sample output:
paul#local:~/src/c/scratch$ ./scanftest
abc
abc
paul#local:~/src/c/scratch$ ./scanftest
abcdefghijlkmnop
abc
paul#local:~/src/c/scratch$
scanf() will add the terminating '\0' for you.
If you don't want to hardcode the length in your format string, you can just construct it dynamically, e.g.:
#include <stdio.h>
#define SYMBOL_MAX_LEN 4
int main(void) {
char buffer[SYMBOL_MAX_LEN];
char fstring[100];
sprintf(fstring, "%%%ds", SYMBOL_MAX_LEN - 1);
scanf(fstring, buffer);
printf("%s\n", buffer);
return 0;
}
For the avoidance of doubt, scanf() is generally a terrible function for dealing with input. fgets() is much better for this type of thing.
Does scanf not prevent values from being recorded in the adjacent blocks of memory after symbol?
As far as I know, No.
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
By using buffer safe functions like fgets.
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
Only if the size was enough for it to put the nul terminator. For example if your array was of length 10 and you input 10 chars how will it put the nul terminator.
I am able to type '01234567890', and the program will still store the entire value?
This is because you are Unlucky that you are getting your desired result. This will invoke undefined behavior.
Does scanf not prevent values from being recorded in the adjacent blocks of memory after symbol?
No.
How could I prevent the user from entering a value of greater than length SYMBOL_MAX_LEN?
Use fgets.
Does scanf put the null terminating character into symbol automatically, or is that something I will need to do manually?
Yes
I have a simple question. I want to write a program in C that scans the lines of a specific file, and if the only phrase on the line is "Atoms", I want it to stop scanning and report which line it was on. This is what I have and is not compiling because apparently I'm comparing an integer to a pointer: (of course "string.h" is included.
char dm;
int test;
test = fscanf(inp,"%s", &dm);
while (test != EOF) {
if (dm=="Amit") {
printf("Found \"Atoms\" on line %d", j);
break;
}
j++;
}
the file was already opened with:
inp = fopen( .. )
And checked to make sure it opens correctly...
I would like to use a different approach though, and was wondering if it could work. Instead of scanning individual strings, could I scan entire lines as such:
// char tt[200];
//
// fgets(tt, 200, inp);
and do something like:
if (tt[] == "Atoms") break;
Thanks!
Amit
Without paying too much attention to your actual code here, the most important mistake your making is that the == operator will NOT compare two strings.
In C, a string is an array of characters, which is simply a pointer. So doing if("abcde" == some_string) will never be true unless they point to the same string!
You want to use a method like "strcmp(char *a, char *b)" which will return 0 if two strings are equal and something else if they're not. "strncmp(char *a, char *b, size_t n)" will compare the first "n" characters in a and b, and return 0 if they're equal, which is good for looking at the beginning of strings (to see if a string starts with a certain set of characters)
You also should NOT be passing a character as the pointer for %s in your fscanf! This will cause it to completely destroy your stack it tries to put many characters into ch, which only has space for a single character! As James says, you want to do something like char ch[BUFSIZE] where BUFSIZE is 1 larger than you ever expect a single line to be, then do "fscanf(inp, "%s", ch);"
Hope that helps!
please be aware that dm is a single char, while you need a char *
more: if (dm=="Amit") is wrong, change it in
if (strcmp(dm, "Amit") == 0)
In the line using fscanf, you are casting a string to the address of a char. Using the %s in fscanf should set the string to a pointer, not an address:
char *dm;
test = fscanf(inp,"%s", dm);
The * symbol declares an indirection, namely, the variable pointed to by dm. The fscanf line will declare dm as a reference to the string captured with the %s delimiter. It will point to the address of the first char in the string.
What kit said is correct too, the strcmp command should be used, not the == compare, as == will just compare the addresses of the strings.
Edit: What kit says below is correct. All pointers should be allocated memory before they are used, or else should be cast to a pre-allocated memory space. You can allocate memory like this:
dm = (char*)malloc(sizeof(char) * STRING_LENGTH);
where STRING_LENGTH is a maximum length of a possible string. This memory allocation only has to be done once.
The problem is you've declared 'dm' as a char, not a malloc'd char* or char[BUFSIZE]
http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/
You'll also probably report incorrect line numbers, you'll need to scan the read-in buffer for '\n' occurences, and handle the case where your desired string lies across buffer boundaries.