As mentioned in the heading, I am having problems while extracting a word from a sentence. It is giving a "break-point error". Can anyone help me understand how am I messing up, as I am just a beginner.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int main()
{
char* word_array[50], input[51], word[51], temp[51];
short i , j, k, flag;
i = j = k = flag = 0;
printf("Enter the sentence (max 50 characters):\n");
gets_s(input, 50);
printf("\nEnter the word to be searched : ");
gets_s(word, 50);
while (input[i] != NULL)
{
while (input[i] == ' ')// skip the spaces
i = i + 1;
k = 0;
while (input[i] != ' ' || input[i] != NULL)//extract the words
{
word_array[j] = (char*)malloc(50 * sizeof(char));
*(*(word_array + j) + k) = input[i];
k = k + 1;
i = i + 1;
}
*(*(word_array + j) + k) = '\0';
printf("\nProcessed word : %s", word_array[j]);//just for debugging
j = j + 1;
}
for (i = 0; i <= j; i++)
if (strcmp(word_array[i], word) == 0)
flag = flag + 1;
printf("\nThe word occurred in the sentence %hu times.\n\n", flag);
system("pause");
return 0;
}
Related
I am trying to solve this challenge:
https://www.hackerrank.com/challenges/structuring-the-document/problem
Basically I have been given a locked stub of code with structs in it and I am supposed to parse a given text. This is an abridged version of my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
#include <ctype.h>
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
};
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));
struct paragraph para[doc.paragraph_count];
for(int i = 0; i < doc.paragraph_count; i++) {
para[i].sentence_count = periods + 1;
para[i].data = malloc((periods + 1) * sizeof(struct sentence));
}
struct sentence sen[para[0].sentence_count];
for(int i = 0; i < para[0].sentence_count; i++) {
sen[i].word_count = spaces + 1;
sen[i].data = malloc((spaces + 1) * sizeof(struct word));
}
struct word word[spaces + periods + 1];
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 can be 0 or 1
}
if(i != strlen(text) && isalpha(text[i + 1]) && text[i] == '.') {
sen[sensub].data[wordno++] = word[wordsub++];
wordno = 0;
para[parasub].data[parano++] = sen[sensub++];
}
if((i != strlen(text) && text[i + 1] == '\n') || i + 1 == strlen(text)) {
sen[sensub++].data[wordno++] = word[wordsub];
wordno = 0;
parano = 0;
para[parasub].data[parano++] = sen[sensub];
doc.data[docsub++] = para[parasub++];
}
}
}
printf("%s\n", para[0].data[0].data[0].data);// should print "hello"
return doc;
}
int main() {
struct document doc;
char * text = "hello world.\nhi.bye.\nwow.";
doc = get_document(text);
printf("%s\n", doc.data[0].data[0].data[0].data);//should also print "hello"
}
The problem is the print statements are not printing "hello". Also if I change the indices in the print statements I get a segmentation error.
Here:
word[wordsub].data[k++] = text[j];
you are accessing data member out of allocated memory.
The problem statement specifies that there are never two terminators after a word. There should also be one word at least.
So, the test phrase
"hello world.\nhi.bye.\nwow."
does not fit, but
"hello world\nhi.bye\nwow"
fits and you will have "hello" printed.
Besides, your algorithm is very complex while the code could be simpler. It was fun to try and I did it.
First, let's use some typedef to write less text!
typedef struct word {
char* data;
} W;
typedef struct sentence {
W* data;
int word_count;//denotes number of words in a sentence
} S;
typedef struct paragraph {
S* data ;
int sentence_count;//denotes number of sentences in a paragraph
} P;
typedef struct document {
P* data;
int paragraph_count;//denotes number of paragraphs in a document
} DOC;
Then the function itself. The logic is simple, do all of the following for each char of text in sequence
in case we have any separator (' ', '.' or '\n') record the word
in case we have a separator ('.' or '\n') record the sentence
in case we have a separator ('\n') record a paragraph
The end of the string counts as the end of a paragraph.
Code
struct document get_document(char* text) {
DOC doc = { NULL, 0 }; // you're the doc, doc
P parr = { NULL, 0 };
S sarr = { NULL, 0 };
int wpos=0;
for(int i=0, l=strlen(text) ; i<=l ; i++) { // <= length! (to deal with \0)
char c = text[i];
if ( ! c) c = '\n'; // End of string simulates end of paragraph
if (c == '\n' || c == '.' || c == ' ') {
// End of word, add it to sentence
W word;
word.data = malloc(i - wpos + 1); // +1 for '\0'
strncpy(word.data, text + wpos, i - wpos); // Copy only the word
word.data[i - wpos] = 0; // 0 terminate it
sarr.data = realloc(sarr.data, sizeof(W) * (sarr.word_count+1));
sarr.data[ sarr.word_count++ ] = word;
wpos = i+1;
if (c == '\n' || c == '.') {
// End of sentence, add it to paragraph
parr.data = realloc(parr.data, sizeof(S) * (parr.sentence_count+1));
parr.data[ parr.sentence_count++ ] = sarr;
sarr.data = NULL; // clear sentences
sarr.word_count = 0;
}
if (c == '\n') {
// End of paragraph, add it to doc
doc.data = realloc(doc.data, sizeof(P) * (doc.paragraph_count+1));
doc.data[ doc.paragraph_count++ ] = parr;
parr.data = NULL; // clear paragraphs
parr.sentence_count = 0;
}
}
}
return doc;
}
Finally, to see if that's working, print all members (using a compliant text!)
int main(int argc, char **argv) {
DOC doc;
char * text = "hello world\nhi.bye\nwow";
doc = get_document(text);
for(int i=0 ; i<doc.paragraph_count ; i++) {
printf("Para %d / %d\n", i, doc.paragraph_count-1);
P para = doc.data[i];
for(int j=0 ; j<para.sentence_count ; j++) {
printf("Sent %d / %d\n", j, para.sentence_count-1);
S sent = para.data[j];
for(int k=0 ; k<sent.word_count ; k++) {
W word = sent.data[k];
printf("Word %d / %d: %s\n", k, sent.word_count-1, word.data);
}
}
}
return 0;
}
We could add a bit of code to avoid the processing of two separators (like a trailing '\n', or ' .'
i have this reverse word function. it simply adding word to new string in reverse order . the problem with this code is it not print the last word ( first word before reverse ) . i dont know why . please help fix my code
char str[100], revstr[100];
int i, j, index, len, startIndex, endIndex;
printf("\n Please Enter any String : ");
gets(str);
len = strlen(str);
index = 0;
endIndex = len - 1;
printf("\n ***** Given String in Reverse Order ***** \n");
for(i = len - 1; i > 0; i--)
{
if(str[i] == ' ')
{
startIndex = i + 1;
for(j = startIndex; j <= endIndex; j++)
{
revstr[index] = str[j];
index++;
}
revstr[index++] = ' ';
endIndex = i - 1;
}
}
printf("\n Given String in Reverse Order = %s", revstr);
return 0;
Here's a working code:
char str[100], revstr[100];
int i, j, index, len, startIndex, endIndex;
printf("\n Please Enter any String : ");
gets(str);
len = strlen(str);
index = 0;
endIndex = len - 1;
printf("\n ***** Given String in Reverse Order ***** \n");
for(i = len - 1; i >= -1; i--)
{
if(i == -1){
startIndex = i + 1;
for(j = startIndex; j <= endIndex; j++)
{
revstr[index] = str[j];
index++;
}
revstr[index++] = ' ';
endIndex = i - 1;
break;
}
if(str[i] == ' ')
{
startIndex = i + 1;
for(j = startIndex; j <= endIndex; j++)
{
revstr[index] = str[j];
index++;
}
revstr[index++] = ' ';
endIndex = i - 1;
}
}
printf("\n Given String in Reverse Order = %s", revstr);
The problem was that you were only including a word if there was a space before it. There will be no space before the first word therefore I made the code go before the first letter and always include the first word forcefully. This code can be broken if there are more spaces than needed in the text.
Why does the final section, Grade, not calculate?
I mean, why is it not carrying through to the final section of the program?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
int main(void)
{
char text[1000];
int number = 0;
int words = 0, i;
int sentences = 0, j;
float l = ((number +1) / (words +1)) * 100;
float s = ((sentences+1) / (words+1)) * 100;
float index = (0.0588 * l) - 0.296 * s - 15.8;
// Text Input = Text //
printf("Text: ");
fgets(text, sizeof(text), stdin);
printf("%s", text);
// Letters = number //
number = strlen(text);
printf("%d letters\n", number);
// Words = words //
for (i = 0; text[i] != '\0'; i++)
{
if (text[i] == ' ' && text[i+1] != ' ')
words++;
}
printf("%d words\n", words);
// Sentences = sentences
for (j = 0; j < strlen(text); j++)
{if (text[j] == '.' || text[j] == '!' || text[j] == '?')
sentences++;
}
printf("%d sentences\n", sentences);
// grade level based on formula //
if (index >= 1 && index <= 16)
{
printf("Grade %f\n", index);
}
else
{
if (index < 1)
{
printf("Before Grade 1\n");
}
if (index > 16)
{
printf("Grade 16+\n");
}
}
}
Any feedback would be of significance.
I suspect it's due to the integer identities assigned to the initial variables of number, words, and sentences, yet I do not have a clue how to improve upon this. It's just the final grade portion that is impeding my progress and understanding.
Currently struggling to solve ex 1.21. The task is: Write a program entab that replaces strings of blanks by the minimum number
of tabs and blanks to achieve the same spacing. Use the same tab stops as for detab . When
either a tab or a single blank would suffice to reach a tab stop, which should be given
preference?
Below is my code i have made so far. I have no problems typing the amount of spaces less than tabsize but when it is bigger than that I get segmentation fault. Could anyone help me, please?
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0)
{
int space = 0;
int pos = 0;
int count = 0;
while (line[count] != '\n')
{
if (line[count] != ' ')
{
space = 0;
output[count] = line[count];
}
else if (line[count] == ' ')
{
pos = count - space;
space++;
if (line[count + 1] != ' ')
{
if (space > TAB)
{
int z = entab(output, pos, space);
count = z;
}
else
{
for (int a = 0; a < space; a++)
output[pos + a] = ' ';
}
}
}
count++;
}
if (line[count] == '\n')
{
output[count] = line[count];
count++;
}
output[count] = '\0';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0)
{
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + 1 + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + 1 + nTabs + b] = ' ';
return pos + nTabs + nSpaces + 1;
}
else if (x == 0)
{
nTabs = space / TAB;
nSpaces = space % TAB;
for (int a = 0; a < nTabs; a++)
output[pos + a] = '\t';
for (int b = 0; b < nSpaces; b++)
output[pos + nTabs + b] = ' ';
return pos + nTabs + nSpaces;
}
}
Because the whitespace sequences of 8 characters are replaced by a single character (the tab), the number of read bytes from the input do not match to the written bytes in the output. A simple solution for this, is to simply keep track of two variables, one for the read bytes from the input, and one for the written bytes to the output. You could do this somewhat neater with pointers, though if you are following the book in a linear fashion, IIRC pointers are introduced later on.
Untested (namely for demonstrative purposes) code below.
NOTE: I took some liberties in reformatting your code for brevity.
#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000
int getmine(char s[], int lim);
int entab(char output[], int pos, int space);
int main()
{
char line[MAXLINE], output[MAXLINE];
int i;
while ((i = getmine(line, MAXLINE)) > 0) {
int space = 0;
int pos = 0;
int read_bytes = 0;
int write_bytes = 0;
while(read_bytes < i) {
if (line[read_bytes] != ' ') {
space = 0;
output[write_bytes++] = line[read_bytes];
}
else if (line[read_bytes] == ' ') {
space++;
if (line[read_bytes + 1] != ' ') {
if (space > TAB) {
write_bytes += entab(output, write_bytes, space);
} else {
for (int i = 0; i < space; i++)
output[write_bytes++] = ' ';
}
}
}
read_bytes++;
}
if (line[read_bytes] == '\n') {
output[write_bytes++] = line[read_bytes];
}
output[write_bytes] = '\0';
printf("%s", output);
}
}
int getmine(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
int entab(char output[], int pos, int space)
{
int nTabs = 0;
int nSpaces = 0;
int x = TAB - (pos % TAB);
if (x > 0) {
output[pos] = '\t';
space = space - x;
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + 1 + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + 1 + nTabs + i] = ' ';
return nTabs + nSpaces + 1;
} else if (x == 0) {
nTabs = space / TAB;
nSpaces = space % TAB;
for (int i = 0; i < nTabs; i++)
output[pos + i] = '\t';
for (int i = 0; i < nSpaces; i++)
output[pos + nTabs + i] = ' ';
}
return nTabs + nSpaces;
}
In my solution I used external variables for index counter of output line.
And I made separated function for converting input array to output array.
#include <stdio.h>
#define TAB 8
#define MAX 100;
int j; //counter of newline
char line[MAX];
char newline[MAX];
int getter(void);
void converter(void);
int entab(int space_counter, int line_index);
int main()
{
extern char line[];
extern char newline[];
int len;
while ((len = getter()) > 0) {
converter();
printf("%s", newline);
}
}
int getter()
{
int c;
int i;
i = 0;
while ((c = getchar()) != EOF && c != '\n' && i < 30-1) {
line[i] = c;
++i;
}
if (c == '\n') {
line[i] = c;
++i;
}
line[i] = '\0';
return i;
}
void converter(void)
{
extern int j;
extern char line[];
extern char newline[];
int space_counter;
int i;
i = j = 0;
space_counter = 0;
while (line[i] != '\0') {
while (line[i] == ' ') {
space_counter++;
i++;
}
if (space_counter > 0) {
j = entab(space_counter, i);
space_counter = 0;
}
else {
newline[j] = line[i];
j++;
i++;
}
}
newline[j] = '\0';
}
int entab(int space_counter, int end_point)
{
extern int j;
extern char newline[];
int new_index;
int start_point;
int tab_qty;
int space_qty;
start_point = end_point - space_counter;
tab_qty = end_point / TAB - start_point / TAB;
if (TAB > start_point)
space_qty = space_counter;
else
space_qty = end_point % TAB;
for (tab_qty; tab_qty > 0; tab_qty--) {
newline[j] = '\t';
j++;
}
for (space_qty; space_qty > 0; space_qty--) {
newline[j] = '|';
j++;
}
return new_index = j;
}
I was asked to write a code that returns the maximum number of anagrams (word made by transposing the letters of another word like the word “secure” is an anagram of “rescue.”).
This is what I did:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char text[1000], angrm1[1000], angrm2[1000];
int i, j, k, count = 1, flag = 0, temp, size = 0, q = 1, counter = 0, max = 0;
char**point;
printf_s("Please enter the sentence, and then press Enter:\n");
gets(text);
strcpy_s(angrm1, 1000, text);
j = 1; i = 0;
for (i = 0; i < strlen(angrm1); i = k + 2) {
for (k = i; angrm1[k + 1] != ' '&&angrm1[k + 1]!=0; k++) {
if (angrm1[i] > angrm1[i + 1]) {
temp = angrm1[k];
angrm1[k] = angrm1[k + 1];
angrm1[k + 1] = temp;
}
}
Blockquote Arrange the words
size = strlen(angrm1);
}
for (i = 0; angrm1[i] != 0; i++)
{
if (angrm1[i] == ' ')
{
angrm1[i] = 0;
count++;
}
}
point = (char*)malloc(sizeof(char)*count);
for (i = 0; i < (size - 1); i++)
{
if (angrm1[i] == 0)
{
point[q] = &point[i + 1];
q++;
}
}
for (i = 0; i < counter; i++)
{
for (q = i + 1; q < counter; q++)
{
if (point[q] == 0 || point[i] == 0)
continue;
if (!strcmp(point[q], point[i]))
{
counter++;
point[q] = 0;
}
}
if (max < counter)
max = counter;
counter = 0;
}
printf_s("The maximum (not yet) number of anagram words in this sentence is %d", &max);
}
The first part works (in my opinion).
But when I check with the debugger, it skips the loop and I get junk.
Can someone please help me by pointing to the problem, and explaining how to fix it?