I just had my first class in C programing at college and I did this:
#include <stdio.h>
int main()
{
char answer='x';
printf("Should the crocodile eat the man? y/n ");
scanf("%s",&answer);
printf("%s",& answer);
if(answer == 'y')
{printf("the man is dead");}
if(answer == 'n')
{printf("the man still alive ");}
}
How can I do the same with strings instead of single characters?
I have tried many things but nothing works.
In C, a string is a sequence of character values followed by a zero-valued terminator. The string "hello" is represented by the sequence {'h', 'e', 'l', 'l', 'o', 0}.
Strings are stored as arrays of char - the array must be large enough to hold the entire string plus the 0 terminator, so to store the string "hello", you need an array of char that's at least 6 elements long.
It's important to remember that an array of char doesn't have to contain a string - you can use it to store character data that's not meant to be interpreted as a string. You can also store more than one string to an array, like so:
/**
* Array size is determined by number of elements in the initializer
*/
char strs[] = {'T','h','i','s',0,'i','s',0,'a',0','t','e','s','t',0};
After this, strs will contain 4 strings: "This", "is", "a", "test".
So, to store the strings "y" or "n", you need an array of char that's at least 2 elements wide.
char answer[2];
To read strings with scanf, you use the %s conversion specifier:
scanf( "%s", answer );
%s tells scanf to skip over any leading whitespace, then read a sequence of non-whitespace characters and store them to the answer array. A 0 terminator will automatically be appended to the array, making it a string.
In this case, you don't need to use the & operator on answer; under most circumstances, an expression of type "array of T" will be converted ("decay") to an expression of type "pointer to T", so the expression answer "decays" from type char [2] to type char *.
To be safe, you should specify a maximum field width so that you don't read more characters than the target array is sized to hold:
scanf( "%1s", answer );
Since we have to reserve an element for the 0 terminator, the field width specifier should be at least 1 less than the size of the target array. Since our target array is sized to hold 2 elements, the field width specifier pretty much has to be 1.
To compare strings, use the strcmp or strncmp library functions:
if ( strcmp( answer, "y" ) == 0 )
{
// process "y" answer
}
Yes, strcmp returns 0 on a match.
You could also do a comparison against individual elements in the array:
if ( answer[0] == 'y' )
{
// process "y" answer
}
Remember
If you want to read a single character from the input stream and store it to a single character object with scanf, you would use the %c conversion specifier:
char answer; // single character, not an array
scanf( " %c", &answer ); // use & operator to obtain pointer, blank skips
// leading whitespace
If you want to read a sequence of non-whitespace characters from the input stream and store them to an array of char with scanf, you would use the %s conversion specifier:
char answer[2]; // array of character
scanf( "%1s", answer ); // do not use & operator to obtain pointer, array
// expressions are converted to pointer expressions
// automatically in this case.
You need to create a buffer to store the string:
char answer[50]; // change 50 to the maximum length of an answer + 1
scanf("%s", answer);
Yes but you need to pass it a buffer for the string and use strcmp instead of == for comparison.
#include <stdio.h>
#include <string.h>
int main()
{
char answer[16];
printf("Should the crocodile eat the man? yes/no ");
scanf("%15s", answer);
printf("%s", answer);
if (strncmp(answer, "yes", 16) == 0) {
printf("the man is dead\n");
} else if (strncmp(answer, "no", 16) == 0) {
printf("the man still alive\n");
}
}
Related
Why does this code actually print out "HI!" ? char *s is an adress to the first character of a string, so in the next line of code when we put variable s into printf it should return an adress to that character to printf which obviously can't be represented as a string with %s. But it does. Why?
#include <stdio.h>
int main(void)
{
char *s = "HI!";
printf("%s\n", s);
}
if you want to print the adress, you have to write printf("%p\n", s); instead of printf("%s\n", s);
7.21.6.1 The fprintf function...
8 The conversion specifiers and their meanings are:
...
s If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.
...
280) No special provisions are made for multibyte characters.
C 2011 Online Draft
The %s conversion specifier expects a pointer to the first character of a string - it will print that character and all characters following it until it sees the 0 terminator.
When you pass an array expression as an argument:
char s[] = "Hi!";
printf( "%s\n", s );
that array expression "decays" to a pointer to the first element.
Hey I got this code where I need to scanf the input of the user (ANO/NE) and store this input into variable "odpoved". How to do that? What I have now looks like it is scanning just the first letter of the input.
char odpoved;
printf("Je vše v pořádku? (ANO/NE)");
scanf("%s", &odpoved);
if(odpoved == "ANO" || odpoved == "ano"){
printf("Super, díky mockrát");
}
else if(odpoved == "NE" || odpoved == "ne"){
printf("To mě mrzí, ale ani já nejsem dokonalý");
}
else{
printf("Promiň, ale zmátl jsi mě. Takovou odpověď neznám!!!");
return 0;
}
The first thing you should know about is that char is a data type consisting of 1 byte and is used to store a single character such as 'a', 'b', 1, 2 etc... there are 256 possible characters which are often represented by the ASCII table ( https://www.ascii-code.com/).
As odpoved is a string you need to make it type char* or equivalently char [] which is a pointer to the first char in the array (string) of characters. The last char in a string is always a terminator byte '\0' used to indicate the end of a string. The null terminator is automatically inserted when the speech marks are used e.g. "sometext" or when %s is used to get input.
The other mistake you have made is to compare strings with == or != signs. This will not work as the first characters will be compared with each other. Hence to compare the characters you will need to use strcmp function provided when the string.h library is included. There are many other useful string functions such as strlen which tell you the length of the string etc.
I wanted to test things out with arrays on C as I'm just starting to learn the language. Here is my code:
#include <stdio.h>
main(){
int i,t;
char orig[5];
for(i=0;i<=4;i++){
orig[i] = '.';
}
printf("%s\n", orig);
}
Here is my output:
.....�
It is exactly that. What are those mysterious characters? What have i done wrong?
%s with printf() expects a pointer to a string, that is, pointer to the initial element of a null terminated character array. Your array is not null terminated.
Thus, in search of the terminating null character, printf() goes out of bound, and subsequently, invokes undefined behavior.
You have to null-terminate your array, if you want that to be used as a string.
Quote: C11, chapter §7.21.6.1, (emphasis mine)
s
If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are
written up to (but not including) the terminating null character. If the
precision is specified, no more than that many bytes are written. If the
precision is not specified or is greater than the size of the array, the array shall
contain a null character.
Quick solution:
Increase the array size by 1, char orig[6];.
Add a null -terminator in the end. After the loop body, add orig[i] = '\0';
And then, print the result.
char orig[5];//creates an array of 5 char. (with indices ranging from 0 to 4)
|?|?|?|0|0|0|0|0|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
for(i=0;i<=4;i++){ //attempts to populate array with '.'
orig[i] = '.';
|?|?|?|.|.|.|.|.|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
This results in a non null terminated char array, which will invoke undefined behavior if used in a function that expects a C string. C strings must contain enough space to allow for null termination. Change your declaration to the following to accommodate.
char orig[6];
Then add the null termination to the end of your loop:
...
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = 0;
Resulting in:
|?|?|?|.|.|.|.|.|0|?|?|?|
| ^memory you do not own
^start of orig
Note: Because the null termination results in a C string, the function using it knows how to interpret its contents (i.e. no undefined behavior), and your mysterious characters are held at bay.
There is a difference between an array and a character array. You can consider a character array is an special case of array in which each element is of type char in C and the array should be ended (terminated) by a character null (ASCII value 0).
%s format specifier with printf() expects a pointer to a character array which is terminated by a null character. Your array is not null terminated and hence, printf function goes beyond 5 characters assigned by you and prints garbage values present after your 5th character ('.').
To solve your issues, you need to statically allocate the character array of size one more than the characters you want to store. In your case, a character array of size 6 will work.
#include <stdio.h>
int main(){
int i,t;
char orig[6]; // If you want to store 5 characters, allocate an array of size 6 to store null character at last position.
for (i=0; i<=4; i++) {
orig[i] = '.';
}
orig[5] = '\0';
printf("%s\n", orig);
}
There is a reason to waste one extra character space for the null character. The reason being whenever you pass any array to a function, then only pointer to first element is passed to the function (pushed in function's stack). This makes for a function impossible to determine the end of the array (means operators like sizeof won't work inside the function and sizeof will return the size of the pointer in your machine). That is the reason, functions like memcpy, memset takes an additional function arguments which mentions the array sizes (or the length upto which you want to operate).
However, using character array, function can determine the size of the array by looking for a special character (null character).
You need to add a NUL character (\0) at the end of your string.
#include <stdio.h>
main()
{
int i,t;
char orig[6];
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = '\0';
printf("%s\n", orig);
}
If you do not know what \0 is, I strongly recommand you to check the ascii table (https://www.asciitable.com/).
Good luck
prinftf takes starting pointer of any memory location, array in this case and print till it encounter a \0 character. These type of strings are called as null terminated strings.
So please add a \0 at the end and put in characters till (size of array - 2) like this :
main(){
int i,t;
char orig[5];
for(i=0;i<4;i++){ //less then size of array -1
orig[i] = '.';
}
orig[i] = '\0'
printf("%s\n", orig);
}
I would like to ask how to identify a sequence in C for example AAAAA & ddddd the sequence is all of the inputted characters must be the same.. How is it possible to achieve that? Do I need to use char ? Here is what i had try
#include<stdio.h>
int main() {
char ch;
scanf("%cccc", &ch);
if (ch = 'c')
printf(&ch);
else
printf("Character is Not the same sequence");
return (0);
}
To compare two characters:
char a = 'a';
char b = 'b';
return a == b; // this compares integer values of two characters
// and returns 1/0 if they do match/do not match
To compare strings:
char str1 = "AAAAA";
char str2 = "aaaaa";
return strcmp(str1, str2);
man strcmp(3):
The strcmp() function compares the two strings s1 and s2. It returns
an integer less than, equal
to, or greater than zero if s1 is found, respectively, to be less than, to match, or be greater
than s2.
The strncmp() function is similar, except it compares the only first (at most) n bytes of s1 and
s2.
Your code contains few bugs. %c format is for scanning single character, use %s for strings. Here:
if (ch = 'c')
you assigned 'c' to ch, not what you wanted. Use == in C for comparisons.
I would try this:
Accept a string as input (instead of a character)
Set up a loop to walk through the string, character by character
Your first character will be the "good" value
If at any time, you encounter a different character, fail out of the loop
If you reach the end of the string without failing, you succeed
Create a Macro for the pattern you want to find. typecast your input to the size of the pattern you want to recognise. Subtract both. If 0 pattern matched. Else,shift right 1 bit and repeat. Example, Pattern to find #define wPAT 0x1234. Input=> U32 dwInput=0x12345678. Result= (U16)dwInput - wPAT . If 0,pattern found. Else, dwInput>>1 and repeat Result= (U16)dwInput - wPAT. Repeat 16 times to find if pattern is present or not
This is my target:
input: string with mixed ASCII characters (uppercase, lowercase, numbers, spaces)
output: string with only uppercase characters
I have this:
#include <stdio.h>
void csere(char s[]){
int i;
for(i=0; s[i]!='\0'; i++){
if('a'<=s[i] && s[i]<='z'){
s[i]-=32;
}
printf("%c", s[i]);
}
}
void main(){
char s[1];
scanf("%s", &s);
csere(s);
}
My problem is:
The function stops at the first 'space' character in the string.
I tried to change the s[i] != '\0' in the 'for' part for i <
strlen(s) or just for s[i], but I still get the same result.
Example: qwerty --> QWERTY, but qwe rty --> QWE
(smaller problem: The program only accepts strings with length less than 12, if i change the 1 to 0 in main function.)
Thanks for help. Sorry for bad English.
scanf only scans non-whitespace characters with the %s modifier. If you want to read everything on a string you should use fgets with stdin as the third parameter:
fgets(s, sizeof s, stdin);
If you really need to use scanf for homework or something, you should use something like:
scanf("%128[^\n]", s);
Also, take note you are not allocating enough space for the string, the fact that it has not crashed is just pure coincidence... you should allocate the space on your array:
char s[128]; // change 128 for max string size
Actually, the fgets() usage I wrote earlier would only read 1 character (including the terminator string) since you only put 1 character on the array... change the array size and it should work.
You could also just use toupper() on ctype.h, but I guess this is some kind of homework or practice.
Furthermore, if you are allowed to use pointers, this would be a shorter (and probably more performant although that'd have to be tested... compilers are good these days :-) ) way to convert to uppercase (notice though it changes your original char array, and doesn't print it, although that'd be easy to modify/add, I'll leave it to you):
void strupper(char *sptr) {
while (*sptr) {
if ((*sptr >= 'a' ) && (*sptr <= 'z')) *sptr -= 32;
sptr++;
}
}
From scanf
s
Matches a sequence of bytes that are not white-space characters. The application shall ensure that the corresponding argument is a pointer to the initial byte of an array of char, signed char, or unsigned char large enough to accept the sequence and a terminating null character code, which shall be added automatically.
This means, with %s, scanf reads a string until it encounters the first white space character. Therefore, your function converts the given string only to the first space.
To the second (smaller) problem, the array s must be large enough for the entire string given. Otherwise, you overwrite the stack space and get undefined behaviour. If you expect larger strings, you must increase the size of s, e.g.
char s[100];