Read second Line of File in C - c

So, I programmed a Cesar Encryption that saves the Position of "Space" Characters in the Second Line of the encryptet File with Numbers (like that:
HMEQSRHLMIV //Encryptet Text (here is Enter normally)
7 //Number where the Space Char is
)
My Problem now is, that when I read the String with fgets(), but it only reads until \n, so how do i get the second Line of the File?
here is my code if that helps.
#include <stdio.h>
#include <stdbool.h>
#define asize 80
void deleteEnter(char[]);
void decrypt(char[], int, char[]);
int main() {
char Message[asize] = {0};
int code = 0;
char encMessageFile[asize + 4] = {};
char encMessage[asize] = {};
char MessageFile[asize] = {};
FILE *fp;
FILE *fp2;
bool open = false;
printf("Gib die verschluesselte Datei an: \t");
fgets(encMessageFile,asize + 4, stdin);
deleteEnter(encMessageFile);
fp = fopen(encMessageFile, "r");
do {
if (fp == NULL) {
printf("\nEs wurde keine Datei gefunden die so heisst\n");
open = false;
fclose(fp);
} else {
open = true;
}
} while (open == false);
fgets(encMessage,asize,fp);
printf("\nGib den Code zum entschluesseln ein: \t");
scanf("%i", &code);
decrypt(encMessage, code, Message);
for (int i = 0; i < asize + 4; ++i) {
if (encMessageFile[i] == '.' && encMessageFile[i + 1] == 'e' && encMessageFile[i + 2] == 'n' && encMessageFile[i + 3] == 'c' && encMessageFile[i + 4] == '\0') {
for (int j = 0; j < i; j++) {
if (encMessageFile[j] != '\0') {
MessageFile[j] = encMessageFile[j];
MessageFile[j + 1] = '\0';
}
}
i = asize + 4;
}
}
fp2 = fopen(MessageFile, "w");
fputs(Message, fp2);
fclose(fp2);
fclose(fp);
remove(encMessageFile);
}
void deleteEnter(char encMessage[]){
for (int i = 0; i < asize; i++) {
if (encMessage[i] == '\0') {
i = asize;
} else if (encMessage[i] == '\n'){
encMessage[i] = '\0';
i = asize;
}
}
}
void decrypt(char encMessage[], int code, char Message[]) {
int a = code % 26;
int LeerPos[asize] = {0};
for (int k = 0; k < asize; k++) {
if (encMessage[k] == '\n'){
for (int i = 0; i < asize; ++i) {
if (encMessage[k + i] != '\0') {
LeerPos[i] = encMessage[k + i] - 80;
} else {
i = asize;
}
}
encMessage[k] = '\0';
}
}
for (int i = 0; i < asize; i++) {
if (encMessage[i] == '\0') {
i = asize;
} else {
for (int j = 0; j < a; j++) {
encMessage[i] = encMessage[i] - 1;
if (encMessage[i] < 'A' && encMessage[i] > 'A' - 2) {
encMessage[i] = 'Z';
}
}
}
}
int x = 0;
for (int l = 0; l < asize; l++) {
for (int i = 0; i < asize; i++) {
if (l == LeerPos[i]) {
Message[l] = ' ';
x++;
} else {
Message[l] = encMessage[l - x];
}
}
}
}
I expect, that the Program after the Decryption the Message is "DIAMOND HIER"
Because a User wantet that I post the Encryption too, here it is:
#include <stdio.h>
#include <stdbool.h>
#define asize 80
void cleanup (char[],char[], int[]);//2 arrays input und endinput
void deleteEnter(char[]);
void toupper(char[]); //endinput
int laenge(char[]); //input pointeranzleer
void encrypt(char[], int);
void Ausgabe(char[], char[], int[]);
//i abspeichern. for schleife in dritte array und array+1 und i++
int main() {
FILE *fp;
int schluessel=0;
char input[asize]={' '};
char endinput[asize]={' '};
char name[asize] = {' '};
bool open = false;
int LeerPos[80] = {0};
do {
printf("Bitte geben Sie den Namen der Datei ein:");
fgets(name, asize, stdin);
deleteEnter(name);
fp = fopen(name, "r");
if (fp == NULL) {
printf("\nEs wurde keine Datei gefunden die so heisst\n");
open = false;
fclose(fp);
} else {
open = true;
}
} while (open == false);
fgets(input, asize, fp);
printf("Bitte geben sie den Schluessel ein:");
scanf("%d",&schluessel);
cleanup(input,endinput, LeerPos);
toupper(endinput);
encrypt(endinput, schluessel);
Ausgabe(endinput, name, LeerPos);
fclose(fp);
return 0;
}
int laenge(char input[asize]){
int i=0;
while(input[i]!='\0'){
i++;
}
return i;
}
void cleanup(char input[asize],char endinput[asize], int LeerPos[]){
int j=0;
int LC = 0;
int lengthIn = laenge(input);
for(int i=0;i<lengthIn;i++){
if(input[i]!=' '){
endinput[j]=input[i];
j++;
} else {
LeerPos[LC] = i;
LC++;
}
}
}
void toupper(char endinput[asize]){
for(int i=0;i<laenge(endinput);i++){
if(endinput[i]>='a'&&endinput[i]<='z'){
endinput[i]=endinput[i]-('z'-'Z');
}
}
}
void encrypt(char S[asize], int code) {
int a = code % 26;
for (int i = 0; i < 80; i++) {
if (S[i] == '\0') {
i = 80;
} else {
for (int j = 0; j < a; j++) {
S[i] = S[i]+1;
if (S[i] == 'Z' + 1) {
S[i] = 'A';
}
}
}
}
}
void Ausgabe(char S[asize], char name[asize], int LeerPos[]) {
FILE *fpOut;
char EName[asize + 4];
char EncEnd[4] = {'.','e','n','c'};
for (int j = 0; j < asize; j++) {
EName[j] = name[j];
}
for (int k = 0; k < asize + 4; k++) {
if (EName[k] == '\0'){
for (int i = k; i < k + 4; ++i) {
EName[i] = EncEnd[i - k];
}
k = asize+4;
}
}
fpOut = fopen(EName, "w");
printf("\nVerschluesselte File: %s", EName);
for (int i = 0; i < asize; i++) {
if (S[i] == '\0') {
i = asize;
}else {
fprintf(fpOut, "%c", S[i]);
}
}
fprintf(fpOut, "%c", '\n');
for (int l = 0; l < asize; l++) {
if (LeerPos[l] != '\0'){
fprintf(fpOut, "%i", LeerPos[l]);
} else {
l = asize;
}
}
remove(name);
fclose(fpOut);
}
void deleteEnter(char S[]) {
for (int i = 0; i < asize ; i++) {
if (S[i] == '\0') {
i = asize;
} else if (S[i] == '\n') {
S[i] = '\0';
}
}
}
Thanks for all the Help.
Arigatou Gozaimasu

Related

C code error, put periods in front of words in a file

I'm new to the forum and I have a problem with this part of my program. What I want to do is a function where every two words of the file you open put 3 dots in front of the word and I don't see where I have the error.
void frase_lenta1(char frase[MAX_F][MAX_C], char frase2[MAX_F][MAX_C])
{
char caracter;
int i, j, cont_p, n;
char fitx; //Nom del fitxer
FILE* fit;
n = cont_p % 2;
cont_p = 0;
for (i = 0; i < MAX_F; i++) {
fit = fopen(fitx, "r");
for (j = 0; j < MAX_C; j++) {
while (frase[i][j] != '.' && frase[i][j] != '\0') {
if (frase[i][j] == ' ') {
cont_p++;
}
if (n == 0) {
frase2[i][j] = frase[i][j];
frase2[i][j] = '.';
frase2[i][j + 1] = '.';
frase2[i][j + 2] = '.';
}
}
}
while ((caracter = fgetc(fit)) != EOF) {
printf("%c", caracter);
}
}
}

Checking NULL pointer segmentation fault in C

I have to split an initial char and create a list of said char which has to end with a NULL so i can iterate over in the main without knowing list size. The problem is that i get a seg fault whenever i try to check if last element is NULL. i am sorry i am still trying to learn both C and english. Thank you all
#include <stdlib.h>
#include <stdio.h>
char **split(const char *s) {
char **split;
unsigned m_size = 0, c_size, i, j, k;
// get s size
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
m_size++;
}
}
m_size++;
split = (char**) malloc(sizeof(char) * (m_size + 1));
int sizes[m_size];
c_size = 0;
// get s words size
for (i = 0, j = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
c_size++;
sizes[j] = c_size;
c_size = 0;
j++;
} else {
c_size++;
}
}
sizes[j] = c_size;
for (i = 0; i < m_size; i++) {
split[i] = (char *) malloc(sizeof(char) * sizes[i]);
}
split[i] = NULL;
for (i = 0, j = 0, k = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
split[j][k] = s[i];
k++;
} else {
split[j][k] = '\0';
j++;
k = 0;
}
}
return split;
}
int main() {
char s[19] = "hello how are you?";
char **splitted;
unsigned i;
splitted = split(s);
if (splitted == NULL) {
return 1;
}
for (i = 0; splitted[i]!=NULL; i++) {
printf("%s\n", splitted[i]);
}
return 0;
}
EDIT
#include <stdlib.h>
#include <stdio.h>
char **split(const char *s) {
char **r;
unsigned word_size = 0;
unsigned list_size = 0, i, j, k;
// get s size
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
word_size++;
} else {
if (word_size > 0) {
list_size++;
word_size = 0;
}
}
}
list_size++;
r = malloc(sizeof(*r) * (list_size + 1));
int char_sizes[list_size];
for (i = 0; i < list_size; char_sizes[i] = 0, i++);
// get s words size
for (i = 0, j = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
char_sizes[j]++;
} else {
if (char_sizes[j] > 0) {
j++;
}
}
}
for (i = 0; i < list_size; i++) {
r[i] = malloc(sizeof(char) * char_sizes[i]);
}
r[i] = NULL;
for (i = 0, j = 0, k = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
r[j][k] = s[i];
k++;
} else {
if (k > 0) {
r[j][k] = '\0';
j++;
k = 0;
}
}
}
return r;
}
void destroy(char **list) {
unsigned i;
for (i = 0; list[i] != NULL; i++) {
free(list[i]);
}
free(list);
}
int main() {
char s[100] = " hello guys how are? you,d 31 3 ";
char **splitted;
unsigned i;
splitted = split(s);
if (splitted == NULL) {
return 1;
}
for (i = 0; splitted[i]!=NULL; i++) {
printf("%s", splitted[i]);
}
destroy(splitted);
return 0;
}
ok guys i followed your tips and i edited my code. leaving this here if someone wants to point out other errors i will appreciate. now it should work even with multiple spaces. thanks to all
Your are requesting an "array" of pointers to char, but you are allocating an "array" of chars:
split = (char**) malloc(sizeof(char) * (m_size + 1));
should become
split = malloc(sizeof(char*) * (m_size + 1));
Note the sizeof(char*). BTW: Note that in C, you should not cast the result of malloc as explained in this SO post.

How to count word occurrences each different word in C

Program should include the words in the table in the same order in
which they appear in the text.
Use string.h, ctype.h, stdio.h, include strtok function
#include<ctype.h>
int main(void)
{
int i,j;
char text[3][80];
char wordList[120][80];
int count = 0;
char* ptr;
for (i = 0; i <= 2; i++) {
gets(&text[i][0]);
}
for (i = 0; i <= 2; i++) {
for (j = 0; text[i][j]!='\0' ; j++) {
text[i][j] = tolower(text[i][j]);
}
}
ptr = strtok(text, " ,.;:!?-()[]<>");
while (ptr != NULL) {
}
I've been thinking for a long time, and I don't know how to try. You could ask me what's wrong with my code, but I don't know the approach at all...
try this...
#include <stdio.h>
#include <string.h>
void main()
{
int count = 0, c = 0, i, j = 0, k, space = 0;
char str[100], p[50][100], str1[20], ptr1[50][100];
char *ptr;
printf("Enter the string\n");
scanf(" %[^\n]s", str);
for (i = 0;i<strlen(str);i++)
if ((str[i] == ' ')||(str[i] == ',' && str[i+1] == ' ')||(str[i] == '.'))
space++;
for (i = 0, j = 0, k = 0;j < strlen(str);j++)
{
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
{
p[i][k] = '\0';
i++;
k = 0;
}
else
p[i][k++] = str[j];
}
k = 0;
for (i = 0;i <= space;i++)
{
for (j = 0;j <= space;j++)
{
if (i == j)
{
strcpy(ptr1[k], p[i]);
k++;
count++;
break;
}
else
{
if (strcmp(ptr1[j], p[i]) != 0)
continue;
else
break;
}
}
}
for (i = 0;i < count;i++)
{
for (j = 0;j <= space;j++)
{
if (strcmp(ptr1[i], p[j]) == 0)
c++;
}
printf("%s -> %d times\n", ptr1[i], c);
c = 0;
}
}
try this
#include <stdio.h>
#include <string.h>
void main()
{
int count = 0, c = 0, i, j = 0, k, space = 0;
char str[100], p[50][100], str1[20], ptr1[50][100];
char *ptr;
printf("Enter the string\n");
scanf(" %[^\n]s", str);
for (i = 0;i<strlen(str);i++)
{
if ((str[i] == ' ')||(str[i] == ',' && str[i+1] == ' ')||(str[i] == '.'))
{
space++;
}
}
for (i = 0, j = 0, k = 0;j < strlen(str);j++)
{
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
{
p[i][k] = '\0';
i++;
k = 0;
}
else
p[i][k++] = str[j];
}
k = 0;
for (i = 0;i <= space;i++)
{
for (j = 0;j <= space;j++)
{
if (i == j)
{
strcpy(ptr1[k], p[i]);
k++;
count++;
break;
}
else
{
if (strcmp(ptr1[j], p[i]) != 0)
continue;
else
break;
}
}
}
for (i = 0;i < count;i++)
{
for (j = 0;j <= space;j++)
{
if (strcmp(ptr1[i], p[j]) == 0)
c++;
}
printf("%s -> %d times\n", ptr1[i], c);
c = 0;
}
}

Not sure why int value is not what it is supposed to be

I'm solving this problem : https://www.hackerrank.com/challenges/structuring-the-document/problem
When I run my program on my IDE (XCode) I can see that word_count int 7428912 is not what it is supposed to be for any input. I am not sure why. I know that I am accessing out of bounds array index but I need someone to show me where exactly. The program outputs correctly and then gives an error. Thread 1: EXC_BAD_ACCESS (code=1, address=0x73696870)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
struct word {
char* data;
};
struct sentence {
struct word* data;
int word_count;//denotes number of words in a sentence
};
struct paragraph {
struct sentence* data ;
int sentence_count;//denotes number of sentences in a paragraph
};
struct document {
struct paragraph* data;
int paragraph_count;//denotes number of paragraphs in a document
};
#include <ctype.h>
struct document get_document(char* text) {
int spaces = 0, periods = 0, newlines = 0;
for(int i = 0; i < strlen(text); i++)
if(text[i] == ' ')
spaces++;
else if(text[i] == '.')
periods++;
else if(text[i] == '\n')
newlines++;
struct document doc;
doc.paragraph_count = newlines + 1;
doc.data = malloc((newlines + 1) * sizeof(struct paragraph));
int inBetweenPeriods = 0, j = 0;
struct paragraph para[doc.paragraph_count];
for(int i = 0; i < doc.paragraph_count; i++) {
for(; j < strlen(text); )
if(text[j] == '.') {
inBetweenPeriods++;
j++;
}
else if(text[j] == '\n' || j == strlen(text) - 1) {
para[i].sentence_count = inBetweenPeriods;
j++;
break;
}
else
j++;
para[i].data = malloc((inBetweenPeriods) * sizeof(struct sentence));
inBetweenPeriods = 0;
}
struct sentence sen[periods];
int sp[periods];
for(int j = 0; j < periods; j++)
sp[j] = 0;
int beg = 0;
int ij = 0;
for(int j = 0; j < strlen(text); j++) {
if(text[j] == '.') {
for(int k = beg; k < j; k++)
if(text[k] == ' ')
sp[ij]++;
ij++;
beg = j + 1;
}
}
for(int i = 0; i < periods; i++) {
sen[i].word_count = sp[i] + 1;//spaces + 1;
sen[i].data = malloc((sp[i] + 1) * sizeof(struct word));
}
struct word word[spaces + periods];
int start = 0, k = 0, wordsub = 0, sensub = 0, parasub = 0, docsub = 0, wordno = 0, parano = 0;
for(int i = 0; i < strlen(text); i++) {
if(text[i] == ' ' || text[i] == '.') {
word[wordsub].data = malloc((i - start) * sizeof(char) + 1);
for(int j = start; j < i; j++)
word[wordsub].data[k++] = text[j];
word[wordsub].data[k++] = '\0';
k = 0;
if(i < strlen(text) - 1 && text[i + 1] == '\n')
start = i + 2;
else
start = i + 1;
if(text[i] == ' ') {
sen[sensub].data[wordno] = word[wordsub];
wordno++; //wordno can be 0 or 1
}
if(i != strlen(text) - 1 && isalpha(text[i + 1]) && text[i] == '.') {
sen[sensub].data[wordno] = word[wordsub];
wordno = 0;
para[parasub].data[parano] = sen[sensub];
sensub++;
parano++;
}
if( (i != strlen(text) - 1 && text[i + 1] == '\n') || i == strlen(text) - 1) {
sen[sensub].data[wordno] = word[wordsub];
wordno = 0;
para[parasub].data[parano++] = sen[sensub];
parano = 0;
doc.data[docsub++] = para[parasub];
parasub++;
sensub++;
}
wordsub++;
}
}
return doc;
}
struct word kth_word_in_mth_sentence_of_nth_paragraph(struct document Doc, int k, int m, int n) {
return Doc.data[n - 1].data[m - 1].data[k - 1];
}
struct sentence kth_sentence_in_mth_paragraph(struct document Doc, int k, int m) {
return Doc.data[m - 1].data[k - 1];
}
struct paragraph kth_paragraph(struct document Doc, int k) {
return Doc.data[k - 1];
}
void print_word(struct word w) {
printf("%s", w.data);
}
void print_sentence(struct sentence sen) {
for(int i = 0; i < sen.word_count; i++) {
print_word(sen.data[i]);
if (i != sen.word_count - 1) {
printf(" ");
}
}
}
void print_paragraph(struct paragraph para) {
for(int i = 0; i < para.sentence_count; i++){
print_sentence(para.data[i]);
printf(".");
}
}
void print_document(struct document doc) {
for(int i = 0; i < doc.paragraph_count; i++) {
print_paragraph(doc.data[i]);
if (i != doc.paragraph_count - 1)
printf("\n");
}
}
char* get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
int main()
{
char* text = get_input_text();
struct document Doc = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3){
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
struct word w = kth_word_in_mth_sentence_of_nth_paragraph(Doc, k, m, n);
print_word(w);
}
else if (type == 2) {
int k, m;
scanf("%d %d", &k, &m);
struct sentence sen= kth_sentence_in_mth_paragraph(Doc, k, m);
print_sentence(sen);
}
else{
int k;
scanf("%d", &k);
struct paragraph para = kth_paragraph(Doc, k);
print_paragraph(para);
}
printf("\n");
}
}
I solved it like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
struct word {
char* data;
};
struct sentence {
struct word* data;
int word_count;//denotes number of words in a sentence
};
struct paragraph {
struct sentence* data ;
int sentence_count;//denotes number of sentences in a paragraph
};
struct document {
struct paragraph* data;
int paragraph_count;//denotes number of paragraphs in a document
};
#include <ctype.h>
struct document get_document(char* text) {
int spaces = 0, periods = 0, newlines = 0;
for(int i = 0; i < strlen(text); i++)
if(text[i] == ' ')
spaces++;
else if(text[i] == '.')
periods++;
else if(text[i] == '\n')
newlines++;
struct document doc;
doc.paragraph_count = newlines + 1;
doc.data = malloc((newlines + 1) * sizeof(struct paragraph));
int inBetweenPeriods = 0, j = 0;
struct paragraph para[doc.paragraph_count];
for(int i = 0; i < doc.paragraph_count; i++) {
for(; j < strlen(text);)
if(text[j] == '.')
{ inBetweenPeriods++;j++;}
else if(text[j] == '\n' || j == strlen(text) - 1)
{j++;break;}else j++;
para[i].sentence_count = inBetweenPeriods;
para[i].data = malloc((inBetweenPeriods) * sizeof(struct sentence));
inBetweenPeriods = 0;
}
struct sentence sen[periods];
int sp[periods];
for(int j = 0; j < periods; j++)
sp[j] = 0;
int beg = 0;
int ij = 0;
for(int j = 0; j < strlen(text); j++) {
if(text[j] == '.') {
for(int k = beg; k < j; k++)
if(text[k] == ' ')
sp[ij]++;
ij++;
beg = j + 1;
}
}
for(int i = 0; i < periods; i++) {
sen[i].word_count = sp[i] + 1;//spaces + 1;
sen[i].data = malloc((sp[i] + 1) * sizeof(struct word));
}
struct word word[spaces + periods];
int start = 0, k = 0, wordsub = 0, sensub = 0, parasub = 0, docsub = 0, wordno = 0, parano = 0;
for(int i = 0; i < strlen(text); i++) {
if(text[i] == ' ' || text[i] == '.') {
word[wordsub].data = malloc((i - start) * sizeof(char) + 1);
for(int j = start; j < i; j++)
word[wordsub].data[k++] = text[j];
word[wordsub].data[k++] = '\0';
k = 0;
if(i < strlen(text) - 1 && text[i + 1] == '\n')
start = i + 2;
else
start = i + 1;
if(text[i] == ' ') {
sen[sensub].data[wordno] = word[wordsub];
wordno++; //wordno can be 0 or 1
}
if(i != strlen(text) - 1 && isalpha(text[i + 1]) && text[i] == '.') {
sen[sensub].data[wordno] = word[wordsub];
wordno = 0;
para[parasub].data[parano] = sen[sensub];
sensub++;
parano++;
}
if( (i != strlen(text) - 1 && text[i + 1] == '\n') || i == strlen(text) - 1) {
sen[sensub].data[wordno] = word[wordsub];
wordno = 0;
para[parasub].data[parano++] = sen[sensub];
parano = 0;
doc.data[docsub++] = para[parasub];
parasub++;
sensub++;
}
wordsub++;
}
}
return doc;
}
struct word kth_word_in_mth_sentence_of_nth_paragraph(struct document Doc, int k, int m, int n) {
return Doc.data[n - 1].data[m - 1].data[k - 1];
}
struct sentence kth_sentence_in_mth_paragraph(struct document Doc, int k, int m) {
return Doc.data[m - 1].data[k - 1];
}
struct paragraph kth_paragraph(struct document Doc, int k) {
return Doc.data[k - 1];
}
void print_word(struct word w) {
printf("%s", w.data);
}
void print_sentence(struct sentence sen) {
for(int i = 0; i < sen.word_count; i++) {
print_word(sen.data[i]);
if (i != sen.word_count - 1) {
printf(" ");
}
}
}
void print_paragraph(struct paragraph para) {
for(int i = 0; i < para.sentence_count; i++){
print_sentence(para.data[i]);
printf(".");
}
}
void print_document(struct document doc) {
for(int i = 0; i < doc.paragraph_count; i++) {
print_paragraph(doc.data[i]);
if (i != doc.paragraph_count - 1)
printf("\n");
}
}
char* get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
int main()
{
char* text = get_input_text();
struct document Doc = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3){
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
struct word w = kth_word_in_mth_sentence_of_nth_paragraph(Doc, k, m, n);
print_word(w);
}
else if (type == 2) {
int k, m;
scanf("%d %d", &k, &m);
struct sentence sen= kth_sentence_in_mth_paragraph(Doc, k, m);
print_sentence(sen);
}
else{
int k;
scanf("%d", &k);
struct paragraph para = kth_paragraph(Doc, k);
print_paragraph(para);
}
printf("\n");
}
}

word frequency of string counter is sometimes wrong

I hope you can help me I worked on this code. The code works like this
user inputs a string for example "hey john, how are you john?
the program erases signs like "'?' , ',' '!' " etc.
the program writes a string after erasing the signs : "hey john how are you john?"
and the code outputs the frequency of each word:
hey : 1
john: 2
how : 1
are : 1
you : 1
but my code counts sometimes wrong. For example when I type "bye bye bye hello hello hello"
the output is :
bye : 3
hello : 1
My code does the john example right, but the bye bye... example wrong.
How do I have to change my code? Thank you
#include <stdio.h>
#include <string.h>
char words[80][80];
void clear_string(char *text);
int extract_and_count(char *source, int *count);
void clearArray(char array[]);
int indexInWords(char string[]);
void print(int countOfWords, int count[]);
int equals(char *string1, char *string2);
int main() {
char string[80];
int count[80];
printf("please enter your text: ");
scanf("%[^\n]s", string);
clear_string(string);
printf("%s\n", string);
int countOfWords = extract_and_count(string, count);
print(countOfWords, count);
return 0;
}
void clear_string(char *text){
int i = 0;
for(;i < strlen(text);++i){
if( text[i] == '.' || text[i] == ',' || text[i] == '!' || text[i] == '?'){
int k = i + 1;
for(; k < strlen(text);++k){
text[k-1] = text[k];
}
k = strlen(text) - 1;
text[k] = ' ';
}
}
}
int extract_and_count(char *source, int *count){
int wordCounter = 0;
char string[80];
int i = 0, k = 0;
clearArray(string);
for(; i < strlen(source);++i, ++k){
if(source[i] != ' '){
string[k] = source[i];
}else{
if(string[0] == '\0'){
break;
}
int index = indexInWords(string);
if(index == -1){
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
}else{
count[index] += 1;
}
clearArray(string);
k = -1;
}
}
return wordCounter;
}
void clearArray(char array[]){
memset(array,0,strlen(array));
//array[0] = '\0';
}
int indexInWords(char string[]){
int i = 0;
for(;i < 80;++i){
if(equals(words[i], string) == 0){
return i;
}
}
return -1;
}
void print(int countOfWords, int count[]){
for(int i = 0;i < countOfWords; ++i){
printf("%s : %d\n",words[i], count[i]);
}
}
int equals(char string1[], char string2[]){
return strcmp(string1, string2);
}
The most significant problem I found was in extract_and_count() -- it doesn't count the last word as it only counts words followed by space. The bandaid is to check if string has anything in it after the loop, and if so, process it. Below is my rework for that fix and general style:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
void clear_string(char *text);
int extract_and_count(char *source, int count[]);
void clearArray(char array[]);
int indexInWords(char string[]);
void print(int countOfWords, int count[]);
bool equals(char *string1, char *string2);
#define BUFFER_SIZE (512)
#define MAX_WORD_COUNT (80)
#define MAX_WORD_SIZE (64)
char words[MAX_WORD_COUNT][MAX_WORD_SIZE];
int main() {
char string[BUFFER_SIZE];
int count[MAX_WORD_COUNT];
printf("Please enter your text: ");
while (fgets(string, BUFFER_SIZE, stdin) == NULL) {
printf("Please (re)enter your text: ");
}
clear_string(string);
int countOfWords = extract_and_count(string, count);
print(countOfWords, count);
return 0;
}
void clear_string(char *text) {
for (int i = 0; i < strlen(text); i++) {
if (text[i] == '.' || text[i] == ',' || text[i] == '!' || text[i] == '?' || text[i] == '\n') {
int length = strlen(text);
for (int k = i + 1; k < length; k++) {
text[k - 1] = text[k];
}
text[length - 1] = '\0';
i--;
}
}
}
int extract_and_count(char *source, int count[]) {
int wordCounter = 0;
char string[MAX_WORD_SIZE] = {'\0'};
for (int i = 0, k = 0; i < strlen(source); i++, k++) {
if (source[i] != ' ') {
string[k] = source[i];
} else {
if (string[0] == '\0') {
break;
}
int index = indexInWords(string);
if (index == -1) {
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
} else {
count[index] += 1;
}
clearArray(string);
k = -1;
}
}
if (string[0] != '\0') {
int index = indexInWords(string);
if (index == -1) {
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
} else {
count[index] += 1;
}
}
return wordCounter;
}
void clearArray(char array[]) {
memset(array, 0, strlen(array));
}
int indexInWords(char string[]) {
for (int i = 0; i < MAX_WORD_COUNT; i++) {
if (equals(words[i], string)) {
return i;
}
}
return -1;
}
void print(int countOfWords, int count[]) {
for (int i = 0; i < countOfWords; i++) {
printf("%s : %d\n", words[i], count[i]);
}
}
bool equals(char string1[], char string2[]) {
return strcmp(string1, string2) == 0;
}
The next most significant issue I see is you don't keep track of how many entries in words[][] are used, so indexInWords() could easily wander off making comparisons against uninitialized memory.
In extract_and_count you break out of the for-loop when you find 2 spaces. Also you did not check for the last word of source. Changed it to:
int extract_and_count(char *source, int *count){
int wordCounter = 0;
char string[80];
int i = 0, k = 0;
clearArray(string);
for(; i < strlen(source)+1;++i, ++k){
if(source[i] != ' ' && source[i] != 0){
string[k] = source[i];
}else{
if(string[0] != '\0'){
int index = indexInWords(string);
if(index == -1){
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
}else{
count[index] += 1;
} }
clearArray(string);
k = -1;
}
}
return wordCounter;
}

Resources