Can you lend me a hand with this word counting code? - c

This code don't count words properly. I don't know if it is wrong on the for or what. Need help.
#include <stdio.h>
#include <stdlib.h>
int count_p(char sentence[100]) {
int i, m = 1;
for (i = 0 ; i < 100 ; i++) {
if (sentence[i] == ' ') {
m += 1;
}
}
return(m);
}
void main() {
char s[100];
int p;
printf("Sentence here: ");
scanf("%s", &s[50]);
p = count_p(sentence);
printf("Words: %d", p);
printf("\n");
}

The %s in scanf stops reading when it found a whitespace. Therefore, ' ' won't appear in s unless it was there as indeterminate value in uninitialized variable.
You can use fgets to read a whole line.
Here is a fixed code that also checks for end of the string.
#include <stdio.h>
#include <stdlib.h>
int count_p(char sentence[100]) {
int i, m = 1;
for (i = 0 ; i < 100 && sentence[i] != '\0'; i++) {
if (sentence[i] == ' ') {
m += 1;
}
}
return(m);
}
int main(void) {
char s[100];
int p;
printf("Sentence here: ");
fgets(s, sizeof(s), stdin);
p = count_p(s);
printf("Words: %d", p);
printf("\n");
return 0;
}

scanf("%s", &s[50]);
Not a correct way to take input and writing at index which is out of bound. Do this instead -
scanf("%99[^\n]", s); // this will read 99 characters and until '\n' is encountered
In main you function call is incorrect -
p = count_p(sentence); // sentence is not declares in main
Call like this -
p = count_p(s); // pass s instead of sentence to function
Also in function count_p change ccondition in for loop as -
size_t i;
size_t len=strlen(s);
for (i = 0 ; i < len ; i++)

You see &s[50] means that you pass a pointer to the 51-th element of s, you then try to access s from the beginning but, the first 50 characters in s were not yet initialized, this leads to undefined behavior.
Also, your loop from 0 to 99 will have the same issue since you might input a string of less than 100 characters, in that case you would be accessing uninitialized data too.
You can fix your program by changing this
scanf("%s", &s[50]);
to
scanf("%99s", s);
and then
for (i = 0 ; i < 100 ; i++) {
to
for (i = 0 ; s[i] != '\0' ; i++) {
because scanf() will append a '\0' to make the array a valid c string, that's also the reason for the "%99s".
Another problem is that, if you want white space characters not to make scanf() stop reading, you need a different specifier, because "%s" stops at the first white space character, this is a suggestion
scanf("%99[^\n]", s);
Or you can do as #MikeCAT suggested and go with fgets(). But be careful with the trailing '\n' in case of fgets().
And finally, altough highly unlikely in this situation, scanf() might fail. To indicate success it returns the number of specifiers actually matched, thus it might indicate partial success too. It's fairly common to see the return value of scanf() ignored, and it's very bad when you have a "%d" specifier for example because then the correspoinding parameter might be accessed before initializing it.

The statement scanf("%s", &s[50]); is in correct in your situation.Since you want to enter a sentence separated by spaces,the correct way of doing it is :
scanf(" %99[^\n]s",sentence);
That will prevent buffer overflow and allow space between words.Also your program does not seem to count words correctly if the sentence has consecutive whitespaces.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_p(char *sentence);
void main()
{
char sentence[100];
printf("Sentence here: ");
scanf(" %99[^\n]s",sentence);
int p = count_p(sentence);
printf("Words: %d", p);
printf("\n");
}
int count_p(char *sentence)
{
int len = strlen(sentence);
int x = 0 , wordCount = 0;
for( int n = 0 ; n < len ; n++ )
{
x++;
if( sentence[n] == ' ' )
x = 0;
if( x == 1 )
wordCount++;
}
return wordCount;
}

Related

Counting Characters and Strings n C

This is one of the assignments for my class and this is the objective of the assignment:
Write a program whose input is a character and a string, and whose output indicates the number of times the character appears in the string. The output should include the input character and use the plural form, n's, if the number of times the characters appears is not exactly 1. You may assume that the string does not contain spaces and will always contain less than 50 characters.
This is the code I have so far and I am new to C programming so I don't know how to declare Strings correctly just yet. So far I learned there are no strings in C like there is in Java and you have to do them as a character array:
#include <stdio.h>
#include <string.h>
int main(void) {
char userChar;
char userString[50];
int count = 0;
for (int i = 0; i < userChar; i++) {
if (userString[i] == userChar)
count++;
}
printf("%d", count);
if (count != 1)
printf("'s");
return 0;
}
For example, if I wanted to input n Monday and output 1 n
What would I need to change in my code to go from n Monday to 1 n
This is the only output I am getting, and it only has outputted one thing correctly:
0's
First, I hope this is not considered cheating :-)
Second, you need to define userChar and userString as arguments for main, and pass them in at run time. They are assigned nothing, so that is why you get
0's
Third, your for condition is wrong. You need this so it only iterates through the length of the string:
for (int i = 0; i < strlen(userString); i++)
Finally, You are not printing the value of userChar prior to the return
At first you need to input a string and a character. To count the number of occurrences of the character in the string you can use standard string function strchr.
The program can look something like the following
#include <stdio.h>
#include <string.h>
int main(void)
{
char userChar = ' ';
char userString[50] = "";
printf( "Enter a string without embedded spaces\nof the length less than %d: ", 50 );
scanf( "%49s", userString );
printf( "Enter a character to search in the string: " );
scanf( " %c", &userChar );
size_t n = 0;
for ( const char *p = userString; ( p = strchr( p, userChar ) ) != NULL; ++p )
{
++n;
}
printf( "%zu%s %c\n", n, n < 2 ? "" : "'s", userChar );
}
The expected output is not 0's, it should include the counted character: for example if the character is n and the string Monday, the output should be
1 n
and if the string is Eeny-meeny-miny-moe, the output would be
3 n's
Here is a modified version:
#include <stdio.h>
int main() {
char userChar;
char userString[50];
int i, count;
printf("Enter character: ");
scanf(" %c", &userChar);
printf("Enter string (single word): ");
// read a word with at most 49 characters
scanf(" %49s", userString);
count = 0;
for (i = 0; userString[i] != '\0'; i++) {
if (userString[i] == userChar)
count++;
}
printf("%d %c", count, userChar);
if (count != 1)
printf("'s");
printf("\n");
return 0;
}

Reversing a string word by word

I'm trying to write a program that reverses a string inputted by the user.
Enter a sentence: you can cage a swallow can't you
Reversal of sentence: you can't swallow a cage can you
So I thought about scanning for the string character by character. Then copying the string from the end to the beginning into a new string. At this point, I know that I've got a new word every time I see a space, so I have to invert the order of the letters that are between two spaces. Here's my code:
#include <stdio.h>
#include <string.h>
int main(){
char sentence[64], reversal[64], reversal_copy[64];
int i = 0, index = 0;
printf("Enter a sentence: ");
while(sentence[strlen(sentence)-1]!= '\n'){
scanf("%c", &sentence[i]);
i++;
}
printf("Reversal of sencente: ");
for(int h = strlen(sentence) - 2, k = 0; h >= 0; h++, k++){
reversal[k] = sentence[h];
strcpy(reversal_copy, reversal);
if(sentence[h] == ' '){
for(int m = h; m >= index && m <= h; m--, index++){
reversal[m] = reversal_copy[index];
}
}
}
printf("Reversal of sentence: %s\n\n", reversal);
return 0;
}
I get a segmentation fault error and I believe it happens around here:
for(int h = strlen(sentence) - 2, k = 0; h >= 0; h++, k++){
reversal[k] = sentence[h];
but I don't quite get why. Could you help me with this?
The condition for your first loop to continue is h >= 0, and as you are incrementing h each time this is going to keep getting bigger until it exceeds the size of sentence and throws the error.
If your intention for that loop is to work backwards through sentence then I think you should decrement h and k (h--, k--), but if the intention is to work forwards through sentence then your condition needs to be changed so that the loop finishes once h has reached the end of sentence
The word order can be reversed using a recursive function.
#include <stdio.h>
#include <string.h>
void reverse ( char *str, char *original) {
char temp[strlen ( str) + 1];
temp[0] = 0;
int offset = 0;
if ( 1 == sscanf ( str, "%s%n", temp, &offset)) {
reverse ( str + offset, original);//recursive call
}
else {//at the end of the original string
*original = 0;//set zero at first character
return;
}
//as recursion unwinds, concatenate the words
strcat ( original, temp);
if ( str != original) {//will be false when unwinds reaches first iteration
strcat ( original, " ");
}
return;
}
int main( void) {
char text[] = "you can cage a swallow can't you";
printf ( "%s\n", text);
reverse ( text, text);
printf ( "%s\n", text);
return 0;
}
For starters:
During the while-loop's 1st iteration strlen() is called on an un-initialised variable. This invokes undefined behaviour. Anything can happen.
In any case of updating a char-array character by character you completely ignore the fact that a 0-terminator is necessary to make a char-array a C-string. Only a C-string may be passed to (most of the) str*() functions.
Also scanf() might fail. Test for this.

Why I am getting extra chars while filling my char array in C?

I am trying to write an application in C and I have a problem: I have some unwanted chars in my string2 array in the code part below:
#include <stdio.h>
#include <string.h>
#define max_len 100
int main() {
char string1[max_len], string2[max_len], string3[max_len], temp[max_len];
int m, n, i, j, k, min_str_len;
puts("Enter your first word: ");
gets(string1);
puts("Enter your second word: ");
gets(string2);
m = strlen(string1);
n = strlen(string2);
min_str_len = ((m < n) ? m : n);
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
for (k = 0; k <= min_str_len; k++) {
if (string1[i] == string2[j]) {
//printf("%s",string2[j]);
temp[k] = string2[j];
break;
}
...
}
}
}
So you see here a part of my code. I am assigning "placozoa" as string1, and "placement" as string2. Please see the line: //printf("%s",string2[j]); When I make this line active, I see:
I did not understand why [] and ' characters are included in string2, I was just expecting to see "plac" there in the output.. The weird thing is, I am printing string2 array right after getting from the user (under gets(string2); line), and I see it is "placement" there.
What is happening in the middle, where is my mistake?
In your print statement, printf("%s",string2[j]); use %c instead of %s,
Because %s always try to convert the printing item to string. And to do that, your compiler has added a null char at the end of it.
So what actually happening right now,
when j == 0, string2[j] is equal to 'p' as a single charcter, but as string it becomes "p\0" where \0 is the null character which means the end of a string.
So, I think, just printing as a single character using %c (character) will solve the problem.

string not being read first time around

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main(void)
{
char *names[6];
int num_entries = 0,i=0,size=0;
string name = (string) malloc(sizeof(char) * 16);
printf("\nHow many names do you want to enter ? \n");
scanf("%d",&num_entries);
for(i=0 ; i < num_entries ; i++)
{
printf("\nEnter a name : ");
gets(name);
size = strlen(name);
names[i] = (string) malloc(sizeof(char)*size + 1);
strcpy(names[i],name);
}
for(i=0 ; i < num_entries ; i++)
puts(names[i]);
}
in this program the string is not read the first time around the loop,however works fine for all subsequent calls,the program simply has to accept n strings,store and display them. owever it executes n-1 times.Solution?also,feel free to point any mistakes in the way pointers,allocation etc. is used,any feedback appreciated .
Call gets before the loop to discard the new line left by scanf.
Or better yet, use the standard workaround to discard unread input:
int c;
while ((c = getchar()) != '\n' && c != EOF);
The issue here, which is typical of the scanf statement, is that it does not use the newline when you entered the number of names you wanted and pressed "enter".
As a result, the newline is stuck in the stdin buffer until you do your next read, which in this case is the first name you try to read, so your first name is simply "newline". To deal with this, use getchar() to eat up the newline character so you don't have that issue anymore.
Typically, as a rule of thumb, you'll almost always want to use a getchar() or something similar after a scanf statement to deal with this issue.
I've modified your code below and works fine for me. I also cleaned it up a bit since some lines were not necessary.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main(void)
{
string names[6];
int num_entries=0, i=0;
string name = malloc(sizeof(char) * 16);
printf("\nHow many names do you want to enter ? \n");
scanf("%d",&num_entries);
getchar();
for(i=0 ; i < num_entries ; i++)
{
printf("\nEnter a name : ");
fgets(name,16,stdin);
names[i] = malloc(sizeof(char)*strlen(name) + 1);
strcpy(names[i],name);
}
for(i=0 ; i < num_entries ; i++)
puts(names[i]);
return 0;
}
Here's the code with all suggestions. Note that Anthony Accioly gets credit for the answer.
int main(void)
{
char *names[6];
int num_entries = 0, i = 0, size = 0, c = 0;
string name = malloc(sizeof(char) * 16);
if ( !name )
{
printf( "Unable to allocate memory for name\n" );
return(1);
}
printf("\nHow many names do you want to enter ? \n");
scanf("%d",&num_entries);
while ((c = getchar()) != '\n' && c != EOF);
for( i = 0 ; i < num_entries; i++)
{
printf("\nEnter a name : ");
gets(name);
size = strlen(name);
names[i] = (string) malloc(sizeof(char)*size + 1);
strcpy(names[i],name);
}
for(i=0 ; i < num_entries ; i++)
puts(names[i]);
return(0);
}
You can also use fflush(stdin); as an alternative to getchar() or the while(...) statement.
P.S.: I am sorry for writing my suggestion here, as I do not have enough reputation to comment.

gets() problem in C

I wrote the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 128
int main ()
{
char mychar , string [SIZE];
int i;
int const count =0 ;
printf ("Please enter your string: \n\n");
fgets (string, SIZE, stdin);
printf ("Please enter char to find: ");
mychar = getchar();
for (i=0 ; (string[i] == '\0') ; i++ )
if ( string[i] == mychar )
count++;
printf ("The char %c appears %d times" ,mychar ,count);
return 0;
}
The problem is that the gcc gives me an error for the 'int const count': " increment of read-only variable ‘count’".
What seems to be wrong ?
Thank !
Try using fgets instead as:
fgets (string, SIZE, stdin);
Why gets is unsafe, has been answered several times on SO. You can see this.
Always use fgets() instead of gets. Also there are lots of stuff to fix. You shouldnt use standard library functions for creating user interface. Standard library is really not designed for that. Instead you should use curses library or something similar. You could also write the program to accept arguments as input.
Short example of proper use of the standard library. This version does not have any error checking so it assumes that user input is correct.
#include <stdio.h>
int main(int artc, char *argv[])
{
/* arguments are strings so assign only the first characte of the
* third argument string. Remember that the first argument ( argv[0] )
* is the name of the program.
*/
char mychar = argv[2][0];
char *string = argv[1];
int i, count = 0;
/* count the occurences of the given character */
for(; *string != '\0'; ++string)
if(*string == mychar) ++count;
printf("The char ‘%c’ appears %d times.\n", mychar, count);
return 0;
}
Usage: ./count "Hello, World!" l
Output: The char ‘l’ appears 3 times.
EDIT: As for the original code. Change == to !=.
for (i=0 ; (string[i] == '\0') ; i++ )
to:
for (i=0 ; (string[i] != '\0') ; i++ )
The comparison was wrong.
To make this example work you should also change the line:
if(*string == mychar) ++count;
into
if(string[i] == mychar) ++count;
Full working example is now:
#include <stdio.h>
int main(int artc, char *argv[])
{
/* arguments are strings so assign only the first characte of the
* third argument string. Remember that the first argument ( argv[0] )
* is the name of the program.
*/
char mychar = argv[2][0];
char *string = argv[1];
int i, count = 0;
/* count the occurences of the given character */
for (i=0 ; (string[i] != '\0') ; i++ )
if(string[i] == mychar) ++count;
printf("The char ‘%c’ appears %d times in the sentence: %s\n", mychar, count, string);
return 0;
}
Consider replace with "scanf( "%s", &string)" instead.
gets is dangerous because it lets you read in more data than you've allocated space for, you can use fgets which specifies how many characters it is going to read in and stops if it finds a newline.
gets is dangerous because it can take in more data than the size of the variable. Thereby exposing the system to attacks and compromising security.
fgets should be used as it limits no. of characters to be read.
This will do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 128
int main()
{
char mychar, string[SIZE];
int i;
int count=0;
printf("Please enter your string: ");
fgets(string, SIZE, stdin);
printf("Please enter char to find: ");
mychar = getchar();
for (i = 0; (string[i] != '\0'); i++)
if (string[i] == mychar) ++count;
printf("The char %c appears %d times in the sentence: %s" ,mychar ,count, string);
return 0;
}

Resources