I am trying to make a simple game similar to the now popular game Wordle, but I am having trouble comparing a user inputted string to that of a pre-existing string. I want to be able to compare the strings as a whole as well as each individual letter in the input and the answer. Here is the code i am working with:
#include <stdio.h>
#include <string.h>
int main()
{
char guess[5];
char answer[5] = "money";
printf("what is your first guess? ");
scanf("%s",&guess);
if (strcmp(guess,answer) == 0){
printf("\nyour guess was correct");
}
else{
printf("Your guess was incorrect");
}
return 0;
}
The user may input significantly more characters than 5-1=4.
Also, use fgets(), not scanf().
char guess[100];
fgets( guess, sizeof(guess), stdin );
Don’t forget to remove the Enter key from the user’s input:
char * p = strchr( guess, '\n' );
if (p) *p = '\0';
When storing constant character arrays, declare it with a pointer:
const char * answer = "money";
If you have a fixed list of answers, use the const array.
When storing mutable character arrays, declare it either with a large space (for future use):
char answer[100] = "money";
or let the compiler declare the exact number of elements you need:
char answer[] = "money";
I presume you will want to randomly select an answer for the user to guess at some point, so the 100-element array is a better choice. Use this if you wish to have a file of answers to use at some point.
You will probably want to normalize the user’s input in some way as well. For example, if all your answers are lowercase, you should transform user input to lowercase before comparing.
#include <ctype.h>
char * stolower( char * s )
{
for (char * p = s; *p; ++p)
*p = tolower( *p );
return s;
}
if (strcmp(tolower(guess),answer) == 0){
C strings like "money" contains 6 chars, with an extra '\0' to mark the end of a string. Which means, when stored with a char array, you'll always need an extra space for '\0' in order to use the char array as a string.
For example, strcmp for char str[10] = "aaa\0bbb" and char[4] = "aaa" will be 0 (equal), because the program will see '\0' as the end of a string, ignoring the extra chars. (btw, the way "aaa" stored in the char array is like this: ['a', 'a', 'a', '\0'])
Related
This is my code for two functions in C:
// Begin
void readTrain(Train_t *train){
printf("Name des Zugs:");
char name[STR];
getlinee(name, STR);
strcpy(train->name, name);
printf("Name des Drivers:");
char namedriver[STR];
getlinee(namedriver, STR);
strcpy(train->driver, namedriver);
}
void getlinee(char *str, long num){
char c;
int i = 0;
while(((c=getchar())!='\n') && (i<num)){
*str = c;
str++;
i++;
}
printf("i is %d\n", i);
*str = '\0';
fflush(stdin);
}
// End
So, with void getlinee(char *str, long num) function I want to get user input to first string char name[STR] and to second char namedriver[STR]. Maximal string size is STR (30 charachters) and if I have at the input more than 30 characters for first string ("Name des Zuges"), which will be stored in name[STR], after that I input second string, which will be stored in namedriver, and then printing FIRST string, I do not get the string from the user input (first 30 characters from input), but also the second string "attached" to this, I simply do not know why...otherwise it works good, if the limit of 30 characters is respected for the first string.
Here my output, when the input is larger than 30 characters for first string, problem is in the row 5 "Zugname", why I also have second string when I m printing just first one...:
Name des Zugs:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
i is 30
Name des Drivers:xxxxxxxx
i is 8
Zugname: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxxxxxxxx
Drivername: xxxxxxxx
I think your issue is that your train->name is not properly terminated with '\0', as a consequence when you call printf("%s", train->name) the function keeps reading memory until it finds '\0'. In your case I guess your structure looks like:
struct Train_t {
//...
char name[STR];
char driver[STR];
//...
};
In getlinee() function, you write '\0' after the last character. In particular, if the input is more than 30 characters long, you copy the first 30 characters, then add '\0' at the 31-th character (name[30]). This is a first buffer overflow.
So where is this '\0' actually written? well, at name[30], even though your not supposed to write there. Then, if you have the structure above when you do strcpy(train->name, name); you will actually copy a 31-bytes long string: 30 chars into train->name, and the '\0' will overflow into train->driver[0]. This is the second buffer overflow.
After this, you override the train->driver buffer so the '\0' disappears and your data in memory basically looks like:
train->name = "aaa...aaa" // no '\0' at the end so printf won't stop reading here
train->driver = "xxx\0" // but there
You have an off-by-one error on your array sizes -- you have arrays of STR chars, and you read up to STR characters into them, but then you store a NUL terminator, requiring (up to) STR + 1 bytes total. So whenever you have a max size input, you run off the end of your array(s) and get undefined behavior.
Pass STR - 1 as the second argument to getlinee for the easiest fix.
Key issues
Size test in wrong order and off-by-one. ((c=getchar())!='\n') && (i<num) --> (i+1<num) && ((c=getchar())!='\n'). Else no room for the null character. Bad form to consume an excess character here.
getlinee() should be declared before first use. Tip: Enable all compiler warnings to save time.
Other
Use int c; not char c; to well distinguish the typical 257 different possible results from getchar().
fflush(stdin); is undefined behavior. Better code would consume excess characters in a line with other code.
void getlinee(char *str, long num) better with size_t num. size_t is the right size type for array sizing and indexing.
int i should be the same type as num.
Better code would also test for EOF.
while((i<num) && ((c=getchar())!='\n') && (c != EOF)){
A better design would return something from getlinee() to indicate success and identify troubles like end-of-file with nothing read, input error, too long a line and parameter trouble like str == NULL, num <= 0.
I believe you have a struct similar to this:
typedef struct train_s
{
//...
char name[STR];
char driver[STR];
//...
} Train_t;
When you attempt to write a '\0' to a string that is longer than STR (30 in this case), you actually write a '\0' to name[STR], which you don't have, since the last element of name with length STR has an index of STR-1 (29 in this case), so you are trying to write a '\0' outside your array.
And, since two strings in this struct are stored one after another, you are writing a '\0' to driver[0], which you immediately overwrite, hence when printing out name, printf doesn't find a '\0' until it reaches the end of driver, so it prints both.
Fixing this should be easy.
Just change:
while(((c=getchar())!='\n') && (i<num))
to:
while(((c=getchar())!='\n') && (i<num - 1))
Or, as I would do it, add 1 to array size:
char name[STR + 1];
char driver[STR + 1];
I am reading a .txt file which contains data in a random form i.e. it contains integers and strings mixed in it.
Sample .txt file:
this is a 22 string 33 sorry222 stack33ing
still yysi288 2nd line
I want to read the file and differentiate all valid string i.e. which do not contain integers concatinated with them. And store those strings in an array.
Any leads on how to differentiate?
You can use #include <ctype.h> for that purpose.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int checkString( const char s[] ) {
unsigned char c;
while ( ( c = *s ) && ( isalpha( c ) || isblank( c ) ) ) ++s;
return *s == '\0';
}
void printNonNumericWords(char str[]) {
int init_size = strlen(str);
char delim[] = " ";
char *ptr = strtok(str, delim);
while(ptr != NULL)
{
if (checkString(ptr))
printf("'%s'\n", ptr);
ptr = strtok(NULL, delim);
}
printf("\n");
}
Call function like this.
printNonNumericWords(this is a 22 string 33 sorry222 stack33ing");
First: I can´t write the programm for you. It is your task to do and beside this i can´t even change things on your code or at least suggest to alter, because you are not providing any code. I can give you only a dusty leading algorithm for this case:
All the words you might see, are not valid strings in the file. It is only one string containing white space characters between each sequence of characters which appear for you as one word or separated string, but it doesn´t.
You have to get the whole string from the file first and store it into an char array, lets name it source, using fgets():
#include <stdio.h>
FILE *input;
char source[200];
input = fopen("text.txt","r");
fgets(source, 200, input);
After that you need to make those "words" separated strings by transport each of the characters of the source string, one after another, to other char arrays and quit writing the characters to them as soon as the space character or the NUL-byte after the last word is provided in the source string. Don´t forget to make a Nul-Byte (\n) terminating each string.
Thereafter you check each, now valid and separated string, if it either is a string that contains numbers or a string without any number.
I wrote a simple C program in Linux that reads a single character from a string. I get some error regarding string functions. This is my code:
#include <stdio.h>
#include <string.h>
void main () {
char arr[10], vv[10];
int i = 0, len;
printf("enter the staement\n");
scanf("%s", arr);
len = strlen(arr);
printf("String laength=%d\n", len);
while ((vv[i] = getchar(arr)) != '\n') {
printf("%d charcter\n");
i++;
}
}
I don't want to use getchar() directly on the input text like this:
arr[i] = getchar();
I want to use getchar() from a stored string like this:
getchar(string array);
But unfortunately I get an error. Can I use the getchar() function directly from a stored string array?
Read about getchar. The link clearly says that getchar is a function that gets a character (an unsigned char) from stdin. Also, it takes no arguments. This would mean that you cannot copy each character of an array to another array using getchar. Just copy it directly using
while( (vv[i] = arr[i]) != '\n')
But I don't think this loop will end as scanf does not include the newline character when scanning a string(%s). So,you got two options:
Use fgets to get input.
Use the following
while( (vv[i] = arr[i]) != '\0')
When you have string in C, it is actually an array of chars which is terminated by '\0'. You do not need any method to get chars from it. Simply get the char as if you were accessing an array.
while((vv[i] = arr[i])!='\n')
As you have you arr[10] it will cause issues when your input is larger than 10 characters including the '\0'. So it is be better to declare it with enough space!
vv is a single char. You may not write vv[i].
Also, are you sure you want \n and not \0 [null]? scanf() won't give you a string with \n in it.
EDIT:
It is still unclear what you want to achieve, but if you want to check the presence of valid characters in the arr or vv, you can
take the base address of the arr or vv into a char *p.
check if (*p++) and do something.
EDIT:
You may try out something like
char * ip = NULL;
char * op = NULL;
int i = 10; //same as array size.
ip = arr;
op = vv;
while( (*op++ = *ip++) && i--)
{
//do something
};
I tried searching for it on google and could not find a simple answer, most of the questions were asking to delete all occurrences of that char from the string and what not.
My pseudo code:
for (e=0;e<length of string;e++){
if (string[e] is not a number/alphabet){
#delete it
}
}
Is there a simple built in way of doing this?
Also another question, I need to do if not isalnum(string[e]), how would I go about doing so?
is it if !(isalnum(string[e])) or is it if (isalnum(string[e]))!=0?
Typically you would build up a second array and copy the valid symbols to that one.
Deleting numbers inside arrays is only possible if you move all trailing numbers down one step, which is very inefficient. If you need a container class where you can easily delete and add items in the middle, you should be using a linked list.
You can treat the return value of isalnum as bool type. Thus either
if ( !isalnum(string[e]) )
or
if ( isalnum(string[e]) !=0 )
are fine and completely equivalent.
You can filter out characters from a string in-place by keeping two indices. That works, because the string can only get shorter and the new string will fit into the old memory. Here's how with two pointers:
int str_alnum(char *str)
{
char *p, *q;
p = q = str;
while (*p) {
if (isalnum(*p)) *q++ = *p;
p++;
}
*q = '\0';
return q - str;
}
p walks the original string, q walks the new string, possibly trailing after p. q - str is the length of the new string, which might be handy as return value.
Note that you have to pass a string that can be modified, i.e. a char array, not a constant string literal.
This is one way to do it if you are using ASCII formatted characters.
char a[256]; // Some string
char destination[256];
char * pos = destination;
for(unigned int i=0;i>strlen(a)-1;++i)
{
if(((a[i]>='A'&& a[i]<='Z') || (a[i]>='a'&& a[i]<='z') || (a[i]>='1'&& a[i]<='9')))
*pos = a[i]; //replaces letter with a whitespace
++pos;
}
*pos = '\0';
Basically what it does it it converts the letter to the corrosponding intenger and then it checks its within the range that represents the letters between A-Z, a-z and 1-9.
Suppose i have array of characters. say char x[100]
Now, i take input from the user and store it in the char array. The user input is less than 100 characters. Now, if i want to do some operation on the valid values, how do i find how many valid values are there in the char array. Is there a C function or some way to find the actual length of valid values which will be less than 100 in this case.
Yes, C has function strlen() (from string.h), which gives you number of characters in char array. How does it know this? By definition, every C "string" must end with the null character. If it does not, you have no way of knowing how long the string is or with other words, values of which memory locations of the array are actually "useful" and which are just some dump. Knowing this, sizeof(your_string) returns the size of the array (in bytes) and NOT length of the string.
Luckily, most C library string functions that create "strings" or read input and store it into a char array will automatically attach null character at the end to terminate the "string". Some do not (for example strncpy() ). Be sure to read their descriptions carefully.
Also, take notice that this means that the buffer supplied must be at least one character longer than the specified input length. So, in your case, you must actually supply char array of length 101 to read in 100 characters (the difference of one byte is for the null character).
Example usage:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = "Hello World";
printf("%lu\n", (unsigned long)strlen(string));
return 0;
}
strlen() is defined as:
size_t strlen(const char * str)
{
const char *s;
for (s = str; *s; ++s);
return(s - str);
}
As you see, the end of a string is found by searching for the first null character in the array.
That depends on entirely where you got the input. Most likely strlen will do the trick.
Every time you enter a string in array in ends with a null character. You just have to find where is the null character in array.
You can do this manually otherwise, strlen() will solve your problem.
char ch;
int len;
while( (ch=getche() ) != '13' )
{
len++;
}
or use strlen after converting from char to string by %s