Counting words in string with c - c

the push to vaccinate children has taken on fresh urgency amid concerns that the new omicron variant of the virus first identified in southern africa and hong kong in late november will spread quickly in the united states causing a surge in infections already back on the rise from the easily transmitted delta variant given the pervasiveness of delta and prospects of new variants spreading in the united states having as much immunity in the population as possible is critical said dr amesh adalja senior scholar at the johns hopkins center for health security
This is my assignment:
replace multiple spaces to one space between words and delete unnecessary spaces at the beginning and the end.
count the words
print edited string
dont use a new string, just edit.
I can't find problem. It should count the words but it can not do. Help me, please.
//Counting words program C
#include <stdio.h>
#define N 5000
int main(void) {
FILE *fp;
char text[N];
int k, d, leng, spacecount = 0;
int m, j, z, i, p, n;
if ((fp = fopen("soru.txt", "r")) == NULL) {
printf("Dosya acma hatasi!");
return 1;
}
fgets(text, N - 1, fp);
while (k < N && text[k] != '\0') {
leng++;
k++;
}
z = leng;
for (i = 0; i < leng; i++) {
if (i = 0 && text[i] == ' ') {
z--;
for (m = 0; m < leng; m++) {
text[m] = text[m + 1];
}
i--;
text[z] == '\0';
} else
if (text[i] ==' ' && text[i + 1] == ' ') {
z--;
for (j = i; j < leng; j++) {
text[j + 1] = text[j + 2];
}
i--;
text[z] == '\0';
} else
if (text[i] == ' ' && text[i + 1] == '\0') {
z--;
for (j = i; j < leng; j++) {
text[j] = text[j + 1];
}
i--;
text[z] == '\0';
} else
if (text[i] == '\0') {
break;
}
}
while (text[d] != '\0') {
if (text[d] == ' ')
spacecount++;
d++;
}
printf("kelime sayisi: %d" , spacecount + 1);
printf("\n cikti:%s ", text);
fclose(fp);
return 0;
}
I can't find problem. It should count the word but it can not do. Help me, please
for(i=0; i < leng; i++) {
if(i=0 && text[i]== ' '){
z--;
for(m=0; m< leng; m++ ){
text[m] = text [m+1];}
i--;
}
else if(1<i<z && text[i] ==' ' && text[i+1] == ' ' ){
z--;
for(j=i; j<leng ; j++) {
text[j+1] = text [j+2];}
i--;
}
else if(i=z && text[i] ==' ' && text[i+1] == '\0' ){
z--;
for(j=i; j<leng ; j++) {
text[j] = text [j+1]; }
i--;
}
},// I think problem in here. Endless loop

Your code is too complicated. You can solve the problem with 2 index variables: one to read the characters from the input line, one to write the relevant characters into the same buffer.
You would keep track of the previous character, starting with space, and detect the beginning of words as the current character is not a space following a space. You would thus count the words and only output a space before each word except the first on a line.
Here is a modified version:
//Counting words program C
#include <stdio.h>
#define N 5000
int main(void) {
FILE *fp;
char text[N];
int total_words = 0;
if ((fp = fopen("soru.txt", "r")) == NULL) {
printf("Dosya açma hatası!\n");
return 1;
}
while (fgets(text, N, fp) != NULL) {
int len = strlen(text);
int word_count = 0;
char c, lastc = ' ';
int i, j;
// strip the trailing newline
if (len > 0 && text[len - 1] == '\n') {
text[--len] == '\0';
}
for (i = j = 0; i < len; i++) {
c = text[i];
if (c != ' ') {
if (lastc == ' ') {
if (word_count > 0) {
// output a space between words
text[j++] = ' ';
}
word_count++;
}
text[j++] = c; // copy the non space character
}
lastc = c;
}
text[j] = '\0'; // set the null terminator
printf("kelime sayısı: %d\n", word_count);
printf("çıktı: %s\n", text);
total_words += word_count;
}
fclose(fp);
printf("\ntoplam kelime sayısı: %d\n", total_words);
return 0;
}
Note a silly bug in your code: if (i = 0 && text[i] == ' ') is parsed as if ((i = (0 && (text[i] == ' '))) != 0) which is always false and sets i to the value 0. C expression syntax is very powerful but somewhat error prone and confusing. I advise you to use -Wall or -Weverything as a compiler option to let the compiler warn about potential mistakes.
Similarly, you should not write if (1<i<z && ...: 1<i<z is parsed as 1<(i<z) which is always false. You must write 1 < i && i < z or more idiomatically i > 1 && i < z

Related

printing similar words from a string-c

i'm new in c programming and i need some help with this function because i cant figure it out,
i need to make a function that receives a string and prints out the similar words (the order of the letters ,the amount of the letters and if the letters are capital or small doesn't matter) for example:
if received "Nanny have you any cheap peach?"
the output is:
Nanny any
cheap peach
i can't use pointers ,and cant use string.h library.
i tried and came up with this but i had no luck on figuring it out
void FindSimilarWords(char str2[]){
int f,i,j,last,count=0,count1=0,k,letter,temp=0;
char word1[wordsize],word2[wordsize];
for (i = SIZE2 - 1; i >= 0; i--)
{
if (str2[i] != ' ' && str2[i] != '\0')
{
last = i;
break;
}
}
for (i = 0; i<= last; i++)
{
k = 0;
j = i;
do {
word1[k] = str2[j];
k++;
j++;
} while (str2[j] != ' '&&str2[j] != '\0');
word1[k] = '\0';
for (letter =last; letter >= j-1; letter--)
{
temp = letter;
while (temp != ' ')
{
count1++;
temp--;
}
f = 0;
for (k--; k >= 0; k--)
{
if (str2[j] == word1[k])
{
count++;
word2[f] = str2[j];
f++;
}
}
if (count == count1)
printf("%s %s\n", word1, word2);
else
while (letter != ' ')
letter--;
}
while (str2[i] != ' ')
i++;
}
}

How do I do reverse sentence in this simple way?

I have a problem with this code which is supposed to make a reverse sentence.
Example:
Input
Hi my name is Robert
Output
Robert is name my Hi
#include <stdio.h>
#define LEN 50
int main(void)
{
char input, terminator = 0, sentence[LEN+1] = {0};
int i, j, last_space = LEN + 1, posc=0;;
int pos[]={0};
printf("\nEnter a sentence: ");
for (i = 0; (input = getchar()) != '\n'; i++)
{
if(input== ' '){
pos[posc]=i;
posc++;
}
if (input == '.' || input == '?' || input == '!')
{
last_space = i;
terminator = input;
break;
}
sentence[i] = input;
}
if (terminator == 0)
{
printf("Sentence needs a terminating character. (./?/!)\n\n");
return 0;
}
printf("Reversal of sentence: ");
for (i = last_space; i > 0; i--)
{
if (sentence[i] == ' ')
{
for (j = i + 1; j != last_space; j++)
{
putchar(sentence[j]);
}
last_space = i;
putchar(sentence[i]);
}
}
while (sentence[i] != '\0' && sentence[i] != ' ')
{
putchar(sentence[i++]);
}
printf("%c\n\n", terminator);
for(int i=sizeof(pos)-1; i>0; i--){
printf("%.*s", sentence[pos[i-1]], sentence[pos[i]]);
}
printf("%c\n\n", terminator);
return 1;
}
This keeps crashing because of the method at the bottom here:
printf("%c\n\n", terminator);
for(int i=sizeof(pos)-1; i>0; i--){
printf("%.*s", sentence[pos[i-1]], sentence[pos[i]]);
}
printf("%c\n\n", terminator);
return 1;
}
Can someone help me fix this snippet of code for me so that both methods work when run? Thanks.
The array of size 1 is created by the line:
int pos[]={0};
And later you are accessing over the array's limit here:
if(input== ' '){
pos[posc]=i;
posc++;
}
The behaviour is undefined after that. The same mistake presents in the code you've mentioned due to sizeof returns the size in bytes, not just amount of elements.
There is a simplest way to do it,
you just have to write a function who will write the last word of the sentence first, then the second and goes on ..
There you can find a working code
#include <unistd.h>
//This function print the last word or a space
static int print_last(const char *str, int len)
{
int i = 0;
while (len > 0 && str[len] == ' ')
len--;
while (i <= len && str[len - i] != ' ')
i++;
write(1, str + len - i + 1, i);
while (len > 0 && str[len] == ' ')
len--;
if (i < len)
write(1, " ", 1);
return (len - i);
}
int main(int ac, char **av)
{
int len = 0;
if (ac == 2)
{
while (av[1][len])
len++;
len--;
while (len > 0)
len = print_last(av[1], len);
}
write(1, "\n", 1);
return (0);
}
and there, once compiled (to compile --> clang yourFileName.c) , you can call the program like so
./youCompiledProgram 'the sentance you want to be inverted'

Calculating the % of comment text in a file

I'm trying to calculate the percentage of comment text in a file but I can't figure out what's wrong with my calculation method.
#include <stdio.h>
#include<stdlib.h>
int main()
{
int k, commNum1 = 0, commNum2 = 0, Nbrackets1 = 0, Nbrackets2 = 0, Cbrackets1 = 0, Cbrackets2 = 0, tabs = 0, spaces = 0;
char str[10000];
char ch, file_name[75];
FILE *fp;
char writtenText[2000];
printf("Enter the name of file you wish to see with extension .c or .txt\n");
gets(file_name);
fp = fopen(file_name, "a"); // reads the file
if (fp == NULL)
{
perror("Error while opening the file.\n");
_getche();
exit(EXIT_FAILURE);
}
printf("Enter a sentence:\n");
gets(writtenText);
fprintf(fp, "%s", writtenText);
fclose(fp);
fp = fopen(file_name, "r");
printf("The contents of %s file are :\n\n", file_name);
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
// printf("%c", ch);
str[i] = ch; //printing and storing process
i++;
}
int fsize = i;
for (k = 0; k < fsize; k++) {
if (str[k] == '(')
Nbrackets1++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == ')')
Nbrackets2++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == '{')
Cbrackets1++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == '}')
Cbrackets2++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == '\t')
tabs++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == ' ')
spaces++;
}
for (k = 0; k < fsize; k++) {
if (str[k] == '/' && str[k + 1] == '*') {
while (str[k] != '*' && str[k + 1] != '/') {
commNum1++;
if (str[k] == ' ') {
commNum1--;
}
// printf("commNum1 = %d\n",commNum1); //just to test if my calculations are correct
k++;
}
}
}
for (k = 0; k < fsize; k++) {
if (str[k] == '/' && str[k + 1] == '/') {
while (str[k] != '\n') {
commNum2++;
if (str[k] == ' ') {
commNum2--;
}
// printf("commNum2 = %d\n",commNum2); //just to test if my calculations are correct
k++;
}
}
}
double commAVG = (commNum1 + commNum2) / fsize * 100;
double avgTAS = (tabs + spaces) / 2;
printf("\n\nOccurence of character ( : %d", Nbrackets1);
printf("\nOccurence of character ) : %d", Nbrackets2);
printf("\nOccurence of character { : %d ", Cbrackets1);
printf("\nOccurence of character } : %d ", Cbrackets2);
printf("\nAverage number of spaces and tabulations: %2.f", avgTAS);
printf("\nPercentage of comment text in the file: %2.f%%", commAVG);
fclose(fp);
return 0;
}
My view is that the for loop goes through the whole array in which the text is stored. If it meets a specific set of characters (/* or //) it starts adding 1 to an int. While adding if it finds spaces in between, it subtracts 1. If it meets another specific character or set of characters (/* or \n) it stops adding and the for loop takes over and finishes searching through the whole array. The problem is that it's calculating something else and I can't figure out the flaw in my method. Thanks !
Lets do a little play through... (the thing you should do with your debugger)
for (k = 0; k < fsize; k++) {
if (str[k] == '/' && str[k + 1] == '*') {
while (str[k] != '*' && str[k + 1] != '/') {
commNum1++;
if (str[k] == ' ') {
commNum1--;
}
// printf("commNum1 = %d\n",commNum1); //just to test if my calculations are correct
k++;
}
}
}
Consider the text "/* abc */"
if (str[0] == '/' && str[1] == '*') // true
while (str[0] != '*' && str[1] != '/') // true
commNum1++;
k++;
while (str[1] != '*' && str[2] != '/') // false, cause str[1] == '*'
End of story.
You should try to first increment k above the comment start and then change the while condition
while (str[k] != '*' || str[k + 1] != '/') // instead of &&
Also, in loops where you use look-ahead, adjust your bounds
for (k = 0; k < (fsize - 1); k++) // instead of k < fsize
Maybe you have more errors, but this is the obvious one.
Edit:
Since you mentioned the 400% problem:
You potentially add the same comment for both, commNum1 and commNum2, if the comment is formed like //* comment text or /*// comment text */
Also, your inner while loops don't check for k < fsize, which means that the check will reach beyond the end of array for the last line in file. There you get undefined behavior, potentially counting after-end-of-file-comments until 400% are reached.
Things I'm not going to address further:
/\
* comment starts here, cause \ is preprocessor line removal which merges the two lines into a /*

Erase blank spaces between string in C

So, I am trying to remove the blanks spaces from a sting input by the user. I already have an option where the program counts the vowels and inverts the string. The one where I need help starts with //espaços. What I did was something like: if the "palavra" string, the original one, has a space (' ') in any position, the new string with no space will have the next char from the string "palavra" in that position:
/*palavra = " o l a _ o l a"
[0][1][2][3][4][5][6]
palavra3 = "o l a o l a"
[0][1][2][3][4][5]*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void) {
char palavra[10];
char palavra2[10];
char palavra3[10];
int i;
int vogais = 0;
int j;
int k;
int espaco = 0;
printf("Introduza uma string: \n");
scanf("%[^\n]", palavra);
//vogais
for (i = 0; palavra[i] != '\0'; i++) {
if (palavra[i] == 'a' || palavra[i] == 'e' || palavra[i] == 'i' ||
palavra[i] == 'o' || palavra[i] == 'u' ||
palavra[i] == 'A' || palavra[i] == 'E' || palavra[i] == 'I' ||
palavra[i] == 'O' || palavra[i] == 'U')
vogais ++;
// else
// printf("");
}
printf("Vogais: %i", vogais);
//invertida
for (i = 0; palavra[i] != '\0'; i++);
{
k = i-1;
}
for (j = 0; j <= i-1; j++) {
palavra2[j] = palavra[k];
k--;
}
printf("\nString invertida: %s", palavra2);
//espaços
for (i = 0; palavra[i]; i++) {
if (palavra[i] == ' ')
palavra3[i] = palavra[i + 1];
//espaco++;
}
// printf("\nNumero de espacos: %i", espaco);
printf("\nString sem espacos: %s", palavra3);
}
Remove the extra ; at the end of for (i = 0; palavra[i] != '\0'; i++);
With the extraneous ;, the loop is empty, the following code executes once with i equal to strlen(palavra).
You can avoid this kind of silly bug by using the Kernighan and Ritchie indentation style: put the { at the end of the line with the if, for, while, do or switch statement. This makes it much less likely to type a spurious ; between the control statement and its block.
To remove the spaces, use the 2 finger method:
//espaços
for (i = j = 0; palavra[i]; i++) {
if (palavra[i] != ' ') {
palavra3[j++] = palavra[i];
}
}
palavra3[j] = '\0'; // set the null terminator
Keep a counter of the new string length k ,check if a character is a space, if it is a space ignore it else increment k and add that character to new string.Example-
int k = 0; //k will be the new string length after the loop
for (int i = 0; palavra[i] != '\0'; i++)
{
if (palavra[i] != ' ')
{
palavra3[k++] = palavra[i];
}
}
palavra3[k] = '\0';
This example also works in the case of multiple consecutive spaces.

C for loop to iterate array different from putc

I'm trying to read from a text file and for non printing ascii characters I would like to print out "^" + "G" as an example of the BELL character. Much like the cat -v command of unix. The problem happens in the for loop where I am supposed to store chars until I hit a newline and then print them out. The for loop is printing "G " for ctrl+G and "t " "e " "s " "t " for test.
int readFile(FILE* inputFile) {
char input[5];
char *arrayEnd = &input[5]+1;
int anyChanges = 1;
int iochar = 0;
int i = 0;
//get index of new line
//substring of position until new line
//print substring position to end.
int printedColumns = 0;
//credit Foster Chapter 2
while (( iochar = getc(inputFile) ) != EOF )
{ //Returns 1 if no changes made, return 0 if any changes have been made.
//printf("character --> %c\n",iochar);
if(iochar != '\n') {
//This if statement checks for normal ascii characters.
//If the output is less than 72 it prints it and increments printedColumns.
if (( ' ' <= iochar ) && ( iochar <= 126 ) ) {
if(*(input + i) == *arrayEnd)
{
i = 0;
}
*(input +i) = iochar;
//printf("input array ---> %c\n",input[i]);
//printf("i:%d\n",i);
//printf("iochar:%d\n",iochar);
//putc(*(input+i), stdout);
i++;
}
//This if statement checks for the non-printing characters.
//New line is not included because it is a special case that is accounted for below
if (iochar <= 31) {
if (*(input + i) == *arrayEnd)
{
i = 0;
}
*(input + i) =94;
putc(*(input+i), stdout);
i++;
if(*(input+i)== *arrayEnd)
{
i = 0;
}
*(input + i) = iochar + 64;
putc(*(input+i), stdout);
printf("\n");
i++;
}
int b = 0;
for (b = 0;b<6;b++){
putc(*(input+b),stdout);
}
}//end if != '\n'
}//end while
return anyChanges;
}//end function
This seems to do a lot of what you're looking for:
#include <stdio.h>
static
int readFile(FILE *inputFile)
{
int numChanged = 0;
int iochar = 0;
while ((iochar = getc(inputFile) ) != EOF)
{
if ((' ' <= iochar && iochar <= 126) || iochar == '\n')
putc(iochar, stdout);
else if (iochar < ' ')
{
putc('^', stdout);
putc(iochar + 'A' - 1, stdout);
numChanged++;
}
else
numChanged++;
}
return numChanged;
}
int main(void)
{
printf("Number of changed characters: %d\n", readFile(stdin));
return 0;
}
It worked correctly on its own source code (no characters to change — no tabs in the source), and it seemed to work correctly on its own binary too. Neither output is exciting enough to quote here. Note that it deletes characters from code 0x7F through 0xFF. You can amend that by adjusting the else clause appropriately for whatever rules you choose to specify. The question was silent on the treatment of such characters.
If you need the last 72 characters of a line, then you need to read whole lines; roll in fgets():
#include <stdio.h>
#include <string.h>
static
int readFile(FILE *fp)
{
int numChanged = 0;
char line[4096];
while (fgets(line, sizeof(line), fp) != 0)
{
size_t len = strlen(line);
if (line[len-1] != '\n')
break; // Damn! Line to long
size_t start = 0;
if (len > 72)
start = len - 72;
for (size_t i = start; i < len; i++)
{
/* The next line is only 70 characters long, but this comment should be truncated */
if ((' ' <= line[i] && line[i] <= 126) || line[i] == '\n')
putc(line[i], stdout);
else if (line[i] < ' ')
{
putc('^', stdout);
putc(line[i] + 'A' - 1, stdout);
numChanged++;
}
else
numChanged++;
}
}
return numChanged;
}
int main(void)
{
printf("Number of changed characters: %d\n", readFile(stdin));
return 0;
}
This code, run on its own, carefully kludged source, yields the interesting part:
start = len - 72;
for (size_t i = start; i < len; i++)
{
ine is only 70 characters long, but this comment should be truncated */
if ((' ' <= line[i] && line[i] <= 126) || line[i] == '\n')
putc(line[i], stdout);
else if (line[i] < ' ')
{
You can decide if I've got an off-by-one error in counting the lengths.

Resources