How to count words on each line of input in C - c

Im trying to make a program so it counts the words on each line.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LINES 50
int main()
{
char text[NUM_LINES];
int count = 0;
int nw = 0;
char *token;
char *space = " ";
printf("Enter the text:\n");
while (fgets(text, NUM_LINES, stdin)){
token = strtok(text, space);
while (token != NULL){
if (strlen(token) > 0){
++nw;
}
token = strtok(NULL, space);
}
if (strcmp(text , "e") == 0 || strcmp(text , "e\n") == 0){
break;
}
}
printf("%d words", nw-1);
return 0;
}
For example if the input is:
Hello my name is John
I would like to have a snack
I like to play tennis
e
My program outputs the total words (17 in this case) how do I count the words on each line individually. So the output I would want is "5 7 5" in this example.

How do I count the words on each line individually?
Simply add a local counter line_word_count.
Suggest expanding the delimiter list to cope with spaces after the last word.
char *space = " \r\n";
while (fgets(text, NUM_LINES, stdin)){
int line_word_count = 0;
token = strtok(text, space);
while (token != NULL){
if (strlen(token) > 0){
line_word_count++;
}
token = strtok(NULL, space);
}
if (strcmp(text , "e") == 0 || strcmp(text , "e\n") == 0){
break;
}
printf("%d ", line_word_count);
nw += line_word_count;
}
printf("\n%d words\n", nw);

Related

How to read from the file and write it in the structure? I have a little trouble with my code

I have to write this code, I mean I should read from the file name of students and their mark, and then sort students by the grow of mark. Now I just want to output only mark. I want to display grades using structures. I don't know where the problem is.
text.file
Jon 3
Alina 5
Ron 1
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
int main()
{
const int N = 3;
int i = 0;
struct student {
char surname[50];
int mark;
};
struct student PI1[N];
char str[50];
const char s[1] = " ";
char* token;
FILE* ptr;
token = strtok(str, s);
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
while (fgets(str, 50, ptr) != NULL){
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
PI1[i].mark = atoi(token);
i++;
}
fclose(ptr);
printf("The marks is:\n");
printf("%d %d %d", PI1[0].mark, PI1[1].mark, PI1[2].mark);
return 0;
}
You need to prevent the program from reading from the file pointer if opening the file fails:
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
perror("test.txt");
return 1; // this could be one way
}
The second argument to strok should be a null terminated string. const char s[1] = " "; only has room for one character. No null terminator (\0). Make it:
const char s[] = " "; // or const char s[2] = " "; or const char *s = " ";
Don't iterate out of bounds. You need to check so that you don't try to put data in PI1[N] etc.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
// ^^^^^^^^
Check that strok actually returns a pointer to a new token. If it doesn't, the line you've read doesn't fulfill the requirements.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
token = strtok(str, s);
if(!token) break; // token check
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
if (token) // token check
PI1[i].mark = atoi(token);
else
break;
i++;
}
You could also skip the strcpy by reading directly into your struct student since char str[50]; has the same length as surname. str should probably be larger though, but for now:
while (i < N && fgets(PI1[i].surname, sizeof PI1[i].surname, ptr) != NULL) {
token = strtok(PI1[i].surname, s);
if(!token) break;
token = strtok(NULL, s);
if (token)
PI1[i].mark = atoi(token);
else
break;
i++;
}
Only print as many marks as you successfully read
printf("The marks are:\n");
for(int idx = 0; idx < i; ++idx) {
printf("%d ", PI1[idx].mark);
}
putchar('\n');

Error when reading strings from CSV (Core Dumped)

I keep getting the same error, I'm new to programming so I'm not so sure if the Syntax is correct.
Every time I run it, it returns Segmentation Fault(core dumped), I'm not even sure If I can open a file with a string (address) instead of the filename in extense.
Also the files I'm reading from are CSV but in txt format.
I'm using C99
#define BUFFER_SIZE 1024
#define TAM_PERGUNTAS 128
struct question{
char category[TAM_PERGUNTAS];
char question[TAM_PERGUNTAS];
char option1[TAM_PERGUNTAS];
char option2[TAM_PERGUNTAS];
char option3[TAM_PERGUNTAS];
char correct[TAM_PERGUNTAS];
};
struct question vec_question[BUFFER_SIZE];
void questions() {
FILE *perguntas;
int numaleat=0;
int num_questions, counter = 0, index, temp_randomizer=0;
char line[BUFFER_SIZE];
char answer[32];
char address[TAM_PERGUNTAS];
address[0] = '\0';
srand(time(NULL));
printf("Digite agora o numero de perguntas desejadas.(MAX 20) : "); //Insert Number of questions
scanf("%d", &num_questions);
printf("\n");
for (counter = 0; counter < num_questions; counter++) {
temp_randomizer = rand() % j; //j Represents the number o CATEGORIES at play and acts as a marker in the SELECTION string
sprintf(address, "%s.txt", SELECTION[temp_randomizer]);
perguntas = fopen(address, "r");
if (perguntas == NULL) {
printf("ERROR OPENING FILE!");
}
index = 0;
while (fgets(line, sizeof(line), perguntas) != NULL) {
strcpy(vec_question[index].category, strtok(line, ";"));
strcpy(vec_question[index].question, strtok(NULL, ";"));
strcpy(vec_question[index].option1, strtok(NULL, ";"));
strcpy(vec_question[index].option2, strtok(NULL, ";"));
strcpy(vec_question[index].option3, strtok(NULL, ";"));
strcpy(vec_question[index].correct, strtok(NULL, ";"));
vec_question[index].correct[strlen(vec_question[index].correct) - 1] = '\0';
index++;
}
fclose(perguntas);
index = 20;
numaleat = rand() % index;
printf("%s : %s\n%s\n%s\n%s",vec_question[numaleat].category,vec_question[numaleat].question,vec_question[numaleat].option1,vec_question[numaleat].option2,vec_question[numaleat].option3);
for (int i = 0; i < num_users; i++) {
printf("\n%s: ", &users[i][20]);
scanf("%s", &answer[32]);
if (answer == vec_question[numaleat].correct)
userspoints[i] += 1;
}
}
}
In general one should assume that functions like strtok can fail.
Sometimes it fails and returns a NULL value. A short record in your input is a likely cause.
Consider using it with a loop, and breaking out of the loop once strtok returns NULL.
I found a simple example here.
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.tutorialspoint.com - website";
const char s[2] = "-";
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
token = strtok(NULL, s);
}
return(0);
}
Note that it does one strtok to get the first token. That might return NULL in which case the loop doesn't run. If it doesn't return NULL then it prints that token, and asks strtok for the next token. It keeps doing that until strtok returns NULL.

Removing a word from a given string

I have been trying to write a code to remove a word from an inputted string as part of my homework. But the thing is the outputted "modified" string never really gets modified and it actually always outputs the inputted string. I'm new to strings so I don't have a perfect understanding of how the string.h library functions work.
#include<stdio.h>
#include<string.h>
int main(void)
{
char str[60], strtemp[60], word[10], * token;
printf("Enter the sentence: ");
gets_s(str);
printf("Enter the word to be deleted: ");
gets_s(word);
int i = 0;
token = strtok(str, " ");
while (token != NULL) {
if (!i && token != word)
strcpy(strtemp, token);
else if (token == word) {
token = strtok(NULL, " ");
continue;
}
else {
strcat(strtemp, " ");
strcat(strtemp, token);
}
token = strtok(NULL, " ");
i++;
}
strcpy(str, strtemp);
printf("Modified string: %s \n", str);
}
Add the following:
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
while ((p = strstr(p, sub)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
You should use the memmove() (written on your post's comment too.)
Reference: this thread of SO.

Sorting string lexicographically in c

I want to sort words of a string in lexicographical order.
For Example:
I have a string: I am Apple
Output should be: am Apple I
Problem (output):
enter the string
hello shamsh
the sorted array:
hello
It's not sorting the string and whole string is not being shown in the output, can anyone help me out here. Thanks!
Program code:
#include<stdio.h>
#include<string.h>
void main()
{
char a[25][25],t[25];
char s[200];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
gets(s);
pch = strtok (s," ,.-");
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
while(pch != NULL)
{
strcpy(a[i],pch);
pch = strtok (NULL, " ,.-");
i++;
}
for(i=0;i<count-1;i++)
{
for(j=i+1;j<count;j++)
{
if(strcmp(a[i],a[j])>0)
{
strcpy(t,a[i]);
strcpy(a[i],a[j]);
strcpy(a[j],t);
}
}
}
printf("the sorted array:\n");
for(i=0;i<count;i++)
printf("%s\n",a[i]);
}
If you try to print your string after you pch = strtok (s," ,.-"), you'll notice that your string is broken up. That's because strtok() is destructive and breaks up the string into tokens so you need to count the number of white spaces before calling strtok():
printf("enter the string\n");
gets(s);
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
pch = strtok (s," ,.-");
Also like Weather Vane said, don't use gets(), use fgets() instead oand remove the '\n' from end of the string afterwards. Also you can use realloc() to assign more memory to a dynamic array instead of using a static array since you wouldn't know the number of words in a string beforehand.
#include <stdlib.h>
#include<stdio.h>
#include<string.h>
void main()
{
char** a = NULL;
char t[25];
char s[512];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
if(fgets(s,512, stdin)==NULL)
{
printf("failed to read string\n");
exit(-1);
}
/*remove '\n' from end of the string*/
char *pos;
if ((pos=strchr(s, '\n')) != NULL)
*pos = '\0';
pch = strtok(s, " ,.-");
while(pch)
{
a = realloc(a, sizeof(char*)*++count);
if(a==NULL)
{
perror("failed to allocate memory\n");
exit(-1);
}
a[count-1] = pch;
pch = strtok(NULL, " ,.-");
}
for(i=0;i<count;i++)
printf("%d: %s\n", i, a[i]);
///...compare array
Use qsort() for this sort of thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 0x100
int strcmp_wrapper(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
int main () {
char buffer[BUF_SIZE], *tokens[BUF_SIZE / 2 + 1];
int i = 0, j = 0;
printf("Enter a string: ");
fgets(buffer, BUF_SIZE, stdin);
tokens[0] = strtok(buffer, " ,.-\n");
while ((tokens[++i] = strtok(NULL, " ,.-\n")));
qsort(tokens, i, sizeof(tokens[0]), strcmp_wrapper);
while (j < i)
printf("%s\n", tokens[j++]);
return 0;
}
below is a compact working way of doing what you want. It prints the words of each line, sorted and separated by one space, without repeating words being repeated (if you want them repeated for sure you will be able to touch the program to make it work)
$ cat pru799.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIMITERS " \t\n,.-()&%$\"\'[]{}+-*/;:##|!\\<>=?"
#define LINE_SIZE 1024
#define MAX_WORDS 256
int compare(const char **p, const char **q)
{
return strcmp(*p, *q);
}
int main()
{
char line[LINE_SIZE];
char *words[MAX_WORDS];
int n_words;
while (fgets(line, sizeof line, stdin)) { /* while not eof */
char *p;
int i;
/* first get the words */
n_words = 0;
for (p = strtok(line, DELIMITERS); p; p = strtok(NULL, DELIMITERS)) {
if (strlen(p) == 0) continue; /* word is zero length */
if (n_words >= MAX_WORDS) {
fprintf(stderr, "MAX_WORDS(%d) exceeded\n", MAX_WORDS);
exit(EXIT_FAILURE);
}
words[n_words++] = p;
} /* for */
/* now we have all the words in the array of strings words, sort it */
qsort(words, n_words, sizeof words[0], (int(*)(const void *, const void *))&compare);
/* now print the words */
for (i = 0; i < n_words; i++) {
if (i) { /* all but the first one */
/* don't repeat words */
if (!strcmp(words[i], words[i-1]))
continue;
printf(" "); /* print a space between words */
}
printf("%s", words[i]);
}
printf("\n");
} /* while */
} /* main */

How to split up a string and count how many times a word is used?

while(token != NULL)
{
// for(position = strcspn(str,token); position >= 0;
// position = strcspn(str, token + 1));
// {
// str2[position] = count++;
// }
}
I think I'm having a logic issue with my code. I'm trying to take in a string from user input and return how many times each word was used and only return each word one time. I think my issue is within the section I have commented out but I'm not entirely sure how to fix or change my code.
For example:
Input: Hello, my cat is saying Hello.
Output: Hello 2
my 1
cat 1
is 1
saying 1
I have modified your code and written little differently,
Please have a look.
int main()
{
char haystack[50] = "Hello my cat is saying Hello";
char needle[10];
int i = 0,j = 0,k = 0;
char *ret = NULL;
int cnt = 0;
while(haystack[i] != NULL)
{
if(haystack[i] == ' ')
{
i++;
}
else
{
//Get each sub strings.
while((haystack[i] != ' ') && (haystack[i] != NULL))
{
needle[k++] = haystack[i];
i++;
}
needle[k] = '\0';
printf("The substring is: %s", needle);
//Find how many times the sub string is there in the string
while(strstr(haystack, needle) != NULL)
{
ret = strstr(haystack, needle);
//Once the Substring is found replace all charecter of that substring with space.
for(j=0;j<k;j++)
{
*(ret+j) = ' ';
}
cnt++;//Count the no of times the substrings found.
}
printf("= %d\n",cnt);
cnt = 0;
k = 0;
}
}
return(0);
}
I have not taken care for the special characters, You can modify to take care of those.
So I have used the string "Hello my cat is saying Hello" instead of "Hello, my cat is saying Hello.". Removed the Comma.
Hope this Helps.
To compute how many times a word is present in a string or line you need a structure to preserve all the different words you have and mainly how many times each word is frequent.
My simple approach, without any optimization, is:
#include <stdio.h>
#include <stdlib.h>
struct wordsDetail
{
char word[100];
int freq;
} wordsDetail;
void updateWords(struct wordsDetail s[], int length, char *token)
{
int i;
for (i = 0; i < length && s[i].word[0] != '\0'; i++) {
if (strcmp(s[i].word, token) == 0) {
s[i].freq++;
return;
}
}
strcpy(s[i].word, token);
s[i].freq++;
}
void printResults(struct wordsDetail s[], int length) {
printf("Words\tFreq\n");
for (int i = 0; i <length && s[i].word[0] != NULL; i++) {
printf("%s\t%d\n", s[i].word, s[i].freq);
}
}
int main(void)
{
struct wordsDetail myWords[100];
int wordsDetailLength = sizeof(myWords) / sizeof(wordsDetail);
const size_t line_size = 1024;
char *str = NULL;
int *str2 = NULL;
int i = 0;
char *token;
for (i = 0; i < wordsDetailLength; i++) {
myWords[i].word[0] = '\0';
myWords[i].freq = 0;
}
if ((str = calloc(line_size, sizeof(char))) == NULL) {
printf("error\n");
exit(-1);
}
printf("Input: ");
if (scanf("%[^\n]", str) != 1) {
printf("error\n");
exit(-1);
}
printf("Output: \n");
token = strtok(str, " .,!");
while (token != NULL) {
updateWords(myWords, wordsDetailLength, token);
token = strtok(NULL, " .,!");
}
printResults(myWords, wordsDetailLength);
return 0;
}
A simple result is:
Input: Hello, my cat is saying Hello to my cat.
Output:
Words Freq
Hello 2
my 2
cat 2
is 1
saying 1
to 1

Resources