Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to write a C program that counts the number of words and spaces in a given string. Here's what I have so far:
#include <stdio.h>
int main()
{
int i, spaces;
char a[30];
printf("enter the string");
scanf("%s", a);
for(i=0 ; a[0]!="\0" ; i++
{
if (a[i]=' ')
{
spaces++;
}
}
printf("Number of spaces is %d", spaces);
printf("Number of words is %d", spaces + 1);
}
It gives me a weird error at 9:19. Help would be much appreciated.
Updated:
#include <stdio.h>
int main()
{
int i,spaces;
char a[100];
printf("enter the string\n");
scanf("%s",a);
for(i=0 ; a[i]!='\0' ; i++)
{
if (a[i]==' ')
{
spaces++;
}
}
printf("the no. of spaces in the string is %d\n",spaces);
printf("the no. of words in the string is %d\n",spaces+1);
}
Now doesn't metter what string I input, it'll say there's 0 spaces and 1 word. Why is this?
The first think, you forgot the for closing parenthese. And the condition expression you must use '\0' instead of "\0". Also you need to check a[i] not a[0].
for(i = 0; a[i] != '\0'; i++)
{
if (a[i] == ' ')
{
spaces++;
}
}
Note that you should initialize spaces to 0 before using it.
spaces = 0;
Update:
Another thing, to input a full string with spaces use fgets() instead of scanf:
fgets(a, 100, stdin);
The first argument is your string, the second is the maximum number of characters to input and the third is the stream from where you will get the input: stdin in your case wich is the standard input stream.
Live exemple: https://eval.in/101504
In C, a char[] literal is written with double quotes ("), and a char literal is written with single quotes ('). Change "\0" to '\0'. This is the source of your "weird error."
The bracket syntax is syntactic sugar for dereferencing an offset pointer to a contiguous block of memory, based on what you declared it would contain. Maybe a crude diagram could help? This is a depiction of a char[5]. It's a pointer block of memory that can hold 5 chars and a null terminator.
['h']['e']['l']['l']['o']['\0']
^
a // you called your char[] a, so I did too
A char* is a pointer to a char. So you could also call a a char*. Say you wanted to access the first 'l' in the char[]... well, you'd have to point to the address exactly 2*sizeof(char) ahead. a[2] is the same thing as *(a+(2*sizeof(char))).
So when you dereferenced your char* you got a char, obviously. But "\0" is a char[] literal (i.e. a string) and you can't compare the two.
Other problems: you should close the parentheses on your for loop, and make your comparison a[i]!='\0' (that way you are checking each char as you iterate through the char[]. I think you also meant to check if(a[i]==' '). Otherwise you will be clearing out your string with spaces :)
A little tip for going forward: if you are comparing a variable to a literal, put the literal first so you're less likely to make typos like that. e.g. ' '==a[i]. If you used = instead you would get an error (because you'd be trying to assign something to a literal).
Edit: since you updated your code, I'd like to point out that you should probably initialize spaces to be 0.
Now I won't take credit for this, but in case someone in the future is reading, fgets is what you're looking to use instead of scanf. Thanks to drch for pointing this out.
You're always comparing a[0] to '\0' so your loop continues endlessly, compare it to a[i].
One more thing is that "\0" is a string (char*), you need to compare it to '\0' which is a char.
The reason you're getting 0 and 1 is because of the way you're using scanf. Using scanf with %s just reads the first string that does not include white space. So if you typed
"The fox jumped over the moon"
The output will be 0 spaces and 1 word. This is because scanf(%s, a) will just put "The" into a and will ignore the rest of the string.
http://www.cplusplus.com/reference/cstdio/scanf/
You can use scanf("[^\r\n]", a). I believe that should get you what you want (or close to it anyway).
Related
I don't understand Why don’t we have to print strings in for loop ? In normal cases we need to print arrays in for loop. For example, if we want to print the array of integers. It will be like this:
int a[n];
for (i = 0; i < n; i++){
printf("%d", a[i]);
}
But for strings like:
char s[100] = " Hello ";
printf("%s\n", s);
it is enough to write the name of array.
EDIT: It seems like I didnt ask my question properly as some of you wrote answers which is not related to my question.I edit my question.
Strings terminate with the empty character '\0', that's how it is possible to know when a string ends even without explicitly passing its length.
The difference is that C-style strings (which are char arrays) are zero-terminated, whereas int arrays are normally not zero terminated.
Theoretically, you could also create an int array which is zero-terminated and print that in a loop:
int a[] = {5,7,3,0};
for (i=0;a[i]!=0;i++)
{
printf("%d",a[i])
}
However, the problem with zero-terminated int arrays is that the number 0 could be a meaningful value, so you cannot be sure that it really is the end of the array when you encounter that value. With strings, however, the ASCII-Code 0 does not represent a meaningful value, so you can be reasonably sure that you have reached the end of the string.
Your example is far from analogous. %d refers to a single integer, while %s refers to an entire (but still single) string.
You are not passing the size of the array n[] to printf either - rather you are calling printf n times. You are printing one int just as you are printing one string.
The actual string length is not known a priori, rather printf iterates the string until it encounters the \0 terminator. Equivalent to:
for( int i = 0; s[i] != '\0'; i++)
{
printf( "%c", s[i] ) ;
}
because
char s[100] = " Hello ";
is equivalent to:
char s[100] = { ' ', 'H', 'e', 'l', 'l', 'o', ' ', '\0' } ;
Strings are multiple characters all at once. You cannot ask for a specific character from a string. If you want to do so, you must refer to it as an array of chars like this
for (i = 0; i < n; i++){
printf("%c", s[i]);
}
It is because you are already providing the parameter which is "%s" to the printf function which already has a definition telling it how to print a string.
Hope it helps.
One of the reason is that char only takes 1 byte of memeory and when you just press a character, the first index of array is filled up completely and it moves on to the next one till it encounters NULL character. This is not the case with integer array where the size is more than 1 byte and is machine dependent. So you cannot escape the first index by just pressing the number less than the maximum range. If you try to do this, it will store your numbers in first index only and hence a for loop is required there.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So I'm trying to make it so that you can write text into a file until you make a newline or type -1. My problem is that when you write, it just keeps going until it crashes and gives the error "Stack around the variable "inputChoice" was corrupted".
I believe the problem is that the program doesn't stop accepting stdin when you want to stop typing (-1, newline) and that causes the error. I've tried with a simple scanf and it works, but you can only write a word. No spaces and it doesn't support multiple lines either. That's why I have to use fgets
Judging from your comments, I assume that there are some basic concepts in C
that you haven't fully understood, yet.
C-Strings
A C-String is a sequence of bytes. This sequence must end with the value 0.
Every value in the sequence represents a character based on the
ASCII encoding, for example the
character 'a' is 97, 'b' is 98, etc. The character '\0' has
the value 0 and it's the character that determines the end of the string.
That's why you hear a lot that C-Strings are '\0'-terminated.
In C you use an array of chars (char string[], char string[SOME VALUE]) to
save a string. For a string of length n, you need an array of dimension n+1, because
you also need one space for the terminating '\0' character.
When dealing with strings, you always have to think about the proper type,
whether your are using an array or a pointer. A pointer
to char doesn't necessarily mean that you are dealing with a C-String!
Why am I telling you this? Because of:
char inputChoice = 0;
printf("Do you wish to save the Input? (Y/N)\n");
scanf("%s", &inputChoice);
I haven't changed much, got very demotivated after trying for a while.
I changed the %s to an %c at scanf(" %c, &inputChoice) and that
seems to have stopped the program from crashing.
which shows that haven't understood the difference between %s and %c.
The %c conversion specifier character tells scanf that it must match a single character and it expects a pointer to char.
man scanf
c
Matches a sequence of characters whose length is specified by the maximum field
width (default 1); the next pointer must be a
pointer to char, and there must be enough room for all the characters
(no terminating null byte is added). The usual skip of
leading white space is suppressed. To skip white space first, use an explicit space in the format.
Forget the bit about the length, it's not important right now.
The important part is in bold. For the format scanf("%c", the function
expects a pointer to char and its not going to write the terminating '\0'
character, it won't be a C-String. If you want to read one letter and one
letter only:
char c;
scanf("%c", &c);
// also possible, but only the first char
// will have a defined value
char c[10];
scanf("%c", c);
The first one is easy to understand. The second one is more interesting: Here
you have an array of char of dimension 10 (i.e it holds 10 chars). scanf
will match a single letter and write it on c[0]. However the result won't be
a C-String, you cannot pass it to puts nor to other functions that expect
C-Strings (like strcpy).
The %s conversion specifier character tells scanf that it must match a sequence of non-white-space characters
man scanf
s
Matches a sequence of non-white-space characters; the next pointer must be a
pointer to the initial element of a character array that is long enough to
hold the input sequence and the terminating null byte ('\0'), which is added
automatically.
Here the result will be that a C-String is saved. You also have to have enough
space to save the string:
char string[10];
scanf("%s", string);
If the strings matches 9 or less characters, everything will be fine, because
for a string of length 9 requires 10 spaces (never forget the terminating
'\0'). If the string matches more than 9 characters, you won't have enough
space in the buffer and a buffer overflow (accessing beyond the size) occurs.
This is an undefined behaviour and anything can happen: your program might
crash, your program might not crash but overwrites another variable and thus
scrwes the flow of your program, it could even kill a kitten somewhere, do
you really want to kill kittens?
So, do you see why your code is wrong?
char inputChoice = 0;
scanf("%s", &inputChoice);
inputChoice is a char variable, it can only hold 1 value.
&inputChoice gives you the address of the inputChoice variable, but the
char after that is out of bound, if you read/write it, you will have an
overflow, thus you kill a kitten. Even if you enter only 1 character, it will
write at least 2 bytes and because you it only has space for one character, a kitten will die.
So, let's talk about your code.
From the perspective of an user: Why would I want to enter lines of text, possibly a lot of lines of text
and then answer "No, I don't want to save the lines". It doesn't make sense to
me.
In my opinion you should first ask the user whether he/she wants to save the
input first, and then ask for the input. If the user doesn't want to save
anything, then there is no point in asking the user to enter anything at
all. But that's just my opinion.
If you really want to stick to your plan, then you have to save every line and
when the user ends entering data, you ask and you save the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERLEN 1024
void printFile () {
int i;
char openFile[BUFFERLEN];
FILE *file;
printf("What file do you wish to write in?\n");
scanf("%s", openFile);
getchar();
file = fopen(openFile, "w");
if (file == NULL) {
printf("Could not open file.\n");
return;
}
// we save here all lines to be saved
char **lines = NULL;
int num_of_lines = 0;
char buffer[BUFFERLEN];
printf("Enter an empty line of -1 to end input\n");
// for simplicity, we assume that no line will be
// larger than BUFFERLEN - 1 chars
while(fgets(buffer, sizeof buffer, stdin))
{
// we should check if the last character is \n,
// if not, buffer was not large enough for the line
// or the stream closed. For simplicity, I will ignore
// these cases
int len = strlen(buffer);
if(buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
if(strcmp(buffer, "") == 0 || strcmp(buffer, "-1") == 0)
break; // either an empty line or user entered "-1"
char *line = strdup(buffer);
if(line == NULL)
break; // if no more memory
// process all lines that already have been entered
char **tmp = realloc(lines, (num_of_lines+1) * sizeof *tmp);
if(tmp == NULL)
{
free(line);
break; // same reason as for strdup failing
}
lines = tmp;
lines[num_of_lines++] = line; // save the line and increase num_of_lines
}
char inputChoice = 0;
printf("Do you wish to save the Input? (Y/N)\n");
scanf("%c", &inputChoice);
getchar();
if (inputChoice == 'Y' || inputChoice == 'y') {
for(i = 0; i < num_of_lines; ++i)
fprintf(file, "%s\n", lines[i]); // writing every line
printf("Your file has been saved\n");
printf("Please press any key to continue");
getchar();
}
// closing FILE buffer
fclose(file);
// free memory
if(num_of_lines)
{
for(i = 0; i < num_of_lines; ++i)
free(lines[i]);
free(lines);
}
}
int main(void)
{
printFile();
return 0;
}
Remarks on the code
I used the same code as yours as the base for mine, so that you can spot the
differences much quicker.
I use the macro BUFFERLEN for declaring the length of the buffers. That's
my style.
Look at the fgets line:
fgets(buffer, sizeof buffer, stdin)
I use here sizeof buffer instead of 1024 or BUFFERLEN. Again, that's my
style, but I think doing this is better, because even if you change the size
of the buffer by changing the macro, or by using another explicit size, sizeof buffer
will always return the correct size. Be aware that this only works when
buffer is an array.
The function strdup returns a pointer a pointer to a new string that
duplicates the argument. It's used to create a new copy of a string. When
using this function, don't forget that you have to free the memory using
free(). strdup is not part of the standard library, it conforms
to SVr4, 4.3BSD, POSIX.1-2001. If you use Windows (I don't use Windows,
I'm not familiar with the Windows ecosystem), this function might not be
present. In that case you can write your own:
char *strdup(const char *s)
{
char *str = malloc(strlen(s) + 1);
if(str == NULL)
return NULL;
strcpy(str, s);
return str;
}
I am trying to create a program that take the input from the user and prints the first character of each word but every time I try to Here is my code.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
char leng[100];
int len;
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
char name[len];
//checking if at end or not
while (name[len] != '\0')
{
if (name[len] == ' ')
printf("%c", name[len + 1]);
len++;
}
}
Every time I give a name it shows an error something like:
index 3 out of bounds for type 'char [len]'
These two lines are incorrect:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
If you translate these into English, their meanings as written are:
Scan a string to the memory at the address of 101st element of the
leng array.
Get the length of the string that starts at the address
of the 101st element of the leng array.
The array index is out of bounds because leng[100] is past the end of the array. Remember that a 100 element array goes from 0 to 99, not from 1 to 100!
You want to be scanning into the base address of the array, and passing the base address of the array into strlen(). I'll leave the syntax for you to figure out from your textbook.
And by the way, you also have a problem in your code because you're reading your data into an array named leng, but your loop is working with an array named len. There are at least two additional problems in your code, but I'll leave them for you to debug.
There are a few things to consider with your code. As #richardschwartz already mentioned, you are not referencing your char arrays correctly. you have:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
You may want the following instead:
scanf("%s", leng);
len = strlen(leng);
Also, keep in mind that scanf with the %s flag will stop reading input once white-space is detected. For example, if you input "hello world",
scanf("%s", leng);
will only catch the characters "hello". To get around this, you could loop scanf to read multiple words and return the first character of each word as you desire.
Lastly, scanf is not advised for beginners though. See paxdiablo's excellent reason regarding lack of overflow protection, here: https://stackoverflow.com/a/1248017/6870832
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];
I'm extremely new to C and am doing a few problems I found in a book I bought. What is wrong with this program?
int main (void)
{
char text[50]='\0';
scanf ("%s", text);
printf("%c", text[49]);
printf("%s", text);
return 0;
}
char text[50]='\0';
is not valid. You could skip initialising text and just declare it
char text[50];
or you could initialise its first element
char text[50]={'\0'};
You're also missing an include of stdio.h and should really check that your scanf call read a string and could give it a max length for the string
if (scanf("%49s", text) == 1)
You want to get rid of:
printf("%c", text[49]);
as you have no idea what's at that memory location if the string is less than 49 chars long.
There is a difference of single quotes and double quotes in C.
double quotes means string
single quotes means character
Line 3 will not compile because the compiler wants you to assign a string to the array of characters.
You can do
char text[50]="\0";
which in effect fills all the 50 bytes with zeros.
You could also do
char text[50]="bla";
which fills the first 3 bytes with "bla" and the rest with zeros. At least my compiler does it like that.
You could also do nothing because you anyway fill it with user input just the next statement.
char text[50];
scanf ("%s", text);
But then you have a problem. Because the very next statement will give you random output if the user has entered a string with less than 49 characters. But if you initialize, well then you output the zero byte, which is also quite useless.
The main point however is to learn the different behaviour of C when dealing with an array of characters.
int main ()
{
char text[50]={'1','2','3','4'};
printf("%c", text[1]);
printf("%c",text[0]);
getch();
return 0;
}
do like this..