So I have a struct that I'm declaring in a function and whenever I try running the program it says that the variable is undeclared. However, that error only appears in that function and it doesn't appear in any other function when I declare that struct.
https://repl.it/#JeevenMann/RelevantWetInverse#main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct wordStruct {
char *charPointer;
int numChars;
int wordPos;
struct wordStruct *nextWord;
} word;
typedef struct sentenceStruct{
word *wordObj;
int lineNum;
int wordCount;
struct sentenceStruct *nextSentence;
} sentence;
typedef struct linkedStructure {
sentence *firstSentence;
int sentenceNum;
} LIST;
void printOut(LIST * sentenceList) {
//Declare variables for sentenceIndex
int sentenceIndex = 0;
//reset sentence Index and print out all words on each line
sentenceIndex = 0;
sentence *currentSentence = sentenceList->firstSentence;
printf("\n\nThis is all the words printed out on the same line as entered:\n");
while (currentSentence != NULL) {
word *currentWord = currentSentence->wordObj;
int wordIndex = 0;
while (currentWord != NULL) {
printf("%s ", currentWord->charPointer);
currentWord = currentWord->nextWord;
}
printf("\n");
currentSentence = currentSentence->nextSentence;
}
}
void storeWords(sentence * sentenceObj, char line[]) {
//Declare count variables and index variables
int index = 0;
int wordCount = 1;
int charCount = 1;
word* currentWord;
char copyWord[1000];
//Delegate memory to wordObject and char array
sentenceObj -> wordObj = (word * ) malloc(sizeof(word));
currentWord = sentenceObj->wordObj;
// Loop though sentence until we reach EOS char
while (line[index] != '\n') {
//check if array index is not a space
if (line[index] != ' ') {
//set char to current index
//increase char count
//realloc more memory to char pointers
copyWord[charCount - 1] = line[index];
charCount++;
//if the next index is a EOS symbol or an empty space
if (line[index + 1] == '\n' || line[index + 1] == ' ') {
sentenceObj -> wordCount = wordCount;
currentWord->numChars = charCount - 1;
currentWord->wordPos = wordCount;
copyWord[charCount-1] = '\0';
currentWord->charPointer = (char * ) malloc(sizeof(char) * charCount);
strcpy(currentWord->charPointer,copyWord);
if (line[index + 1] == ' ') {
wordCount++;
charCount = 1;
currentWord->nextWord = (word * ) malloc(sizeof(word));
currentWord = currentWord->nextWord;
currentWord->nextWord = NULL;
strcpy(copyWord,"");
}
}
}
index++;
}
}
LIST * readInput() {
//declare variables for str and lineNum
char str[1000] = "";
int lineNum = 1;
LIST *sentenceList = (LIST *) calloc(1,sizeof(LIST));
sentence *currentSentence;
sentenceList->firstSentence = (sentence * ) calloc(1, sizeof(sentence));
currentSentence = sentenceList->firstSentence;
//while the user doesn't enter an empty string, continue
printf("Enter a string: ");
fgets(str,sizeof(str),stdin);
printf("%s\n",str );
while (strcmp(str, "\n") != 0){
//user hasn't entered an empty string so allocate more memory and populate
//the struct
currentSentence->lineNum = lineNum;
storeWords(currentSentence, str);
lineNum = lineNum + 1;
printf("Enter a string: ");
fgets(str,sizeof(str),stdin);
printf("%s\n",str );
if (strcmp(str, "\n") != 0) {
currentSentence->nextSentence = (sentence * ) calloc(1, sizeof(sentence));
currentSentence = currentSentence->nextSentence;
currentSentence->nextSentence = NULL;
}
}
//print out the sentence as defined by assignment
printOut(sentenceList);
return sentenceList;
}
int searchSentences(LIST * sentenceList, char word[]) {
//Declare variables for the sentence index and return int boolean if word is found
int sentenceIndex = 0;
int wordFound = 0;
//loop through sentenceObjects and print out if that word matches word to find
sentence *currentSentence = sentenceList->firstSentence;
printf("\n\nThis is all the words printed out on the same line as entered:\n");
while (currentSentence != NULL) {
word *theWord = currentSentence->wordObj;
int wordIndex = 0;
while (theWord != NULL) {
if (strcmp(theWord->charPointer,word) == 0) {
printf("%s found in line %d position %d\n", word, currentSentence->lineNum, theWord.wordPos);
wordFound = 1;
}
theWord = theWord->nextWord;
}
printf("\n");
currentSentence = currentSentence->nextSentence;
}
return wordFound;
}
void findString(LIST * sentenceList) {
//declare char array
char str[1000];
//while the user doesn't enter an empty string continue to search for the word
do {
printf("\n\nEnter a word to search for:\n");
fgets(str,sizeof(str),stdin);
str[strlen(str)-1] = '\0';
if (strcmp(str, "") != 0 && searchSentences(sentenceList, str) == 0) {
printf("%s was not found in this file\n", str);
}
} while (strcmp(str, "") != 0);
}
int main() {
//Declare line objects
LIST *sentenceList;
//get Number of lines and ask user for info
sentenceList = readInput();
findString(sentenceList);
return 0;
}
Thanks, I've been trying to fix this for a while now, but I can't seem to figure out why it's not working.
Related
I have a my_string object made that contains a char pointer, a size, and a capacity. I am trying to read words from a dictionary text file into the my_string object and print them to the screen. The default capacity is 7, so when I read a word that is longer than 7 characters, I need to reallocate some space at the end of the string. I haven't been able to implement this functionality correctly yet. It seems to work correctly, but when I run it in valgrind, there is apparently a memory leak somewhere in my code. Not sure where this is coming from, because I free the entire string after the program runs. If someone could help me with this you'd be a lifesaver. Here is my driver code, and my my_string.c file:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
int main(int argc, char* argv[]) {
MY_STRING hMy_String = NULL;
FILE* fp;
hMy_String = my_string_init_default();
fp = fopen("dictionary.txt", "r");
int len;
while(my_string_extraction(hMy_String, fp)) {
len = my_string_get_size(hMy_String);
if(len == 8){
my_string_insertion(hMy_String, stdout);
printf("\n");
if(fgetc(fp) == ' '){
printf("Found a space after the string\n");
}
}
}
my_string_destroy(&hMy_String);
fclose(fp);
return 0;
}
my_string.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
struct my_string {
int size;
int capacity;
char* data;
};
typedef struct my_string My_String;
MY_STRING my_string_init_default(void){
//default capacity of string is 7
//initializes pointer to My_String, set to NULL for good practice
My_String* pMy_String = NULL;
//allocates memory for default string
pMy_String = (My_String*)malloc(sizeof(My_String));
if(pMy_String != NULL) {
pMy_String->size = 0;
pMy_String->capacity = 7;
pMy_String->data = (char*)malloc(sizeof(char) * pMy_String->capacity);
if(pMy_String->data == NULL) {
free(pMy_String);
pMy_String = NULL;
}
}
//returns copy of address to default string
return pMy_String;
}
MY_STRING my_string_init_c_string(char* c_string) {
int i = 0;
//initializes a pointer to a My_String
My_String* theString = NULL;
//loops through string, for every character, i increases 1
while((*c_string) != '\0'){
c_string++;
i++;
}
//resets c_strings value from before the loop
c_string = c_string - i;
i++; //i needs to be 1 greater than the length of the string
//allocation
theString = malloc(sizeof(My_String) + i);
//if there was an error, return NULL
if(theString == NULL)
return NULL;
else {
//sets the values of the object to the given values
(*theString).size = (i - 1);
(*theString).capacity = i;
(*theString).data = c_string;
}
//returns address of the initialized string
return theString;
}
int my_string_get_capacity(MY_STRING hMy_string){
return sizeof(hMy_string);
}
int my_string_get_size(MY_STRING hMy_string) {
char* str = (char*) hMy_string;
int size = 0;
while(str[size] != '\0')
size++;
return size;
}
int my_string_compare(MY_STRING hLeft_string, MY_STRING hRight_string) {
// sets the strings to pointers to the My_String data type
My_String* Left = hLeft_string;
My_String* Right = hRight_string;
//variables for lexicographical value of each string
int left_lex = 0;
int right_lex = 0;
//loops through left string, adds up left_lex value
while((*Left->data) != '\0') {
left_lex += (*Left->data);
(*Left).data++;
}
//loops through right string, adds up right_lex value
while((*Right->data) != '\0') {
right_lex += (*Right->data);
(*Right).data++;
}
//does the comparison and returns the corrosponding value
if(left_lex < right_lex){
return -1;
}else if (left_lex == right_lex) {
return 0;
}else {
return 1;
}
}
Status my_string_extraction(MY_STRING hMy_string, FILE* fp) {
My_String* pMy_string = hMy_string;
int start = 0, end = 0;
char ch;
int strLength, capacity, i;
while(!feof(fp)){
ch = fgetc(fp);
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r') {
continue;
}
else {
start = ftell(fp) - 1;
end = start + 1;
break;
}
}
if(end == 0){
return FAILURE;
}
while(!feof(fp)) {
ch = fgetc(fp);
end++;
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r'){
break;
}
}
strLength = end - start - 1;
(*pMy_string).size = strLength;
if(strLength == 0){
return FAILURE;
}
capacity = my_string_get_capacity(hMy_string);
if(strLength >= capacity){
hMy_string = realloc(hMy_string, strLength + 1);
}
fseek(fp, start, SEEK_SET);
char* str = (char*)hMy_string;
for(i = 0; i < strLength; i++) {
str[i] = fgetc(fp);
}
str[i] = '\0';
return SUCCESS;
}
Status my_string_insertion(MY_STRING hMy_string, FILE* fp) {
char* str = (char*)hMy_string;
if(fprintf(fp, "%s", str))
return SUCCESS;
else
return FAILURE;
}
void my_string_destroy(MY_STRING* phMy_string){
free(*phMy_string);
*phMy_string = NULL;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The code is given. I need to count number of words that are non identical. In order to do that i need to compare them using stcrmp. By looking the code below, how i need to construct while or if statements to compare words in a file by using double linked list? I suppose this condition should be in the main to print it then. My condition doesn't work. Also, can you give some advice where and how to sort words by their length here?
To understand the code some explanation:
This program holds a doubly linked list that will read a file that is entered as a command line argument, read each line from file, tokenize each word from line and for each word will place it into a Word Length structure depending on its length and then will place it into a word_count structure dependent on the word's string and count each word's occurrence in a file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DELIM " ,.+-=!?:;\t"
#define MAXLINE 25000
typedef struct word_count {
char *word;
int count;
struct word_count *next;
struct word_count *prev;
} WORD;
typedef struct word_length_count {
int length;
int count;
WORD *words;
struct word_length_count *next;
struct word_length_count *prev;
} WLENGTH;
int splitIntoWords(char line[]);
void processLength(char *word);
void processWord(char *word, WORD *wordCount);
void printWordLength();
WLENGTH *createWordLength(char *word);
WORD *createWordCount(char *word);
WLENGTH *wordLength = NULL;
int main(unsigned int argc, unsigned char *argv[]) {
FILE *fpin;
char line[MAXLINE];
int totalWordCount = 0;
if ((fpin = fopen(argv[1], "r")) == NULL) {
printf("Can't open input file.\n");
exit(-1);
}
printf("This is the words all tokenized from the input!\n");
while (fgets(line, MAXLINE, fpin) != NULL) {
line[strcspn(line, "\n")] = '\0';
if (line[0] == '\0')
continue;
totalWordCount += splitIntoWords(line);
}
printf("Total number of words is: %d\n", totalWordCount);
printWordLength();
printf("\nFINISHED!");
}
int splitIntoWords(char line[]) {
char *word;
int count=0;
word = strtok(line, DELIM);
for (;word != NULL;) {
count++;
printf("%s\n", word);
processLength(word);
word = strtok(NULL, DELIM);
}
return count;
}
void processLength(char *word)
{
WLENGTH *wLCounter = NULL;
WLENGTH *wLLast = NULL;
if (wordLength == NULL) {
wordLength = createWordLength(word);
return;
}
wLCounter = wordLength;
while (wLCounter != NULL) {
if (strlen(word) == wLCounter->length) {
++wLCounter->count;
processWord(word, wLCounter->words);
return;
}
wLLast = wLCounter;
wLCounter = wLCounter->next;
}
wLLast->next = createWordLength(word);
}
void processWord(char *word, WORD *wordCount) {
WORD *wCounter = NULL;
WORD *wLast = NULL;
if (wordCount == NULL) {
wordCount = createWordCount(word);
return;
}
wCounter = wordCount;
while (wCounter != NULL) {
if (strcmp(word, wCounter->word) == 0) {
++wCounter->count;
return;
}
wLast = wCounter;
wCounter = wCounter->next;
}
wLast->next = createWordCount(word);
}
WLENGTH *createWordLength(char *word) {
WLENGTH *wLCounter = NULL;
wLCounter = (WLENGTH*)malloc(sizeof(WLENGTH));
wLCounter->words = createWordCount(word);
wLCounter->count = 1;
wLCounter->length = strlen(word);
wLCounter->next = NULL;
return wLCounter;
}
WORD *createWordCount(char *word) {
WORD *wCount = NULL;
wCount = (WORD*)malloc(sizeof(WORD));
wCount->word = (char*)malloc(strlen(word+1));
strcpy(wCount->word, word);
wCount->count = 1;
wCount->next = NULL;
return wCount;
}
void printWordLength() {
WLENGTH *temp = wordLength;
WORD *tempWORD = wordLength->words;
while (temp != NULL) {
WORD *tempWORD = wordLength->words;
tempWORD = temp->words;
printf("\nFor Word Length: %d : There are: %d occurances!\n", temp->length, temp->count);
while (tempWORD != NULL) {
printf("\t%s\toccurs:%d\n", tempWORD->word, tempWORD->count);
tempWORD = tempWORD->next;
}
}
}
You're missing this at the bottom of the outermost while loop of printWordLength():
temp = temp->next;
That's why it goes into an infinite loop (which you didn't tell us).
Now, to count distinct words you just need to count every WORD* in every WORDLENGTH*, which you can do while you're printing them in printWordLength():
void printWordLength()
{
WLENGTH * temp = wordLength;
WORD * tempWORD = wordLength->words;
unsigned int unique_words = 0;
while(temp != NULL)
{
WORD * tempWORD = wordLength->words;
tempWORD = temp->words;
printf("\nFor Word Length: %d : There are: %d occurences!\n",
temp->length, temp->count);
while(tempWORD != NULL)
{
printf("\t%s\toccurs:%d\n", tempWORD->word, tempWORD->count);
unique_words++;
tempWORD = tempWORD->next;
}
temp = temp->next;
}
printf("\nThere are %u unique words\n", unique_words);
}
Example:
void stringEvaluation(char *name){
if (strstr(name, "Tall") != NULL)
--here I would like to print only "John Doe"--
}
int main{
char name[160 + 1];
scanf("%[^\n]%*c", name);
stringEvaluation(name);
return 0;
}
and this is the input
"John Doe (45). Black. Tall. Brown eyes"
Your request is unclear. For example, do as follows.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void stringEvaluation(const char *s){
const char *p;
if(s == NULL || *s == '\0'){
puts("invalid format.");
return ;
}
(p = strchr(s, '(')) || (p = strchr(s, '.'));
if(p == NULL){
puts("invalid format.");
return ;
}
//find end
while(!isalpha((unsigned char)p[-1]))
--p;
while(s < p)
putchar(*s++);
}
int main(void){
char name[160 + 1] = "";
scanf("%160[^\n]%*c", name);
stringEvaluation(name);
return 0;
}
I am using strtok() to get the name. Please note, this will work only if you have "()" in your string.
void stringEvaluation(char *name){
if (strstr(name, "Tall") != NULL)
{
char *nameEnd = strtok(name, "("); //Returns address of '('
if(NULL != nameEnd)
{
int nameLength = nameEnd - name - 1; // 1 for space after name.
char *onlyName = malloc((nameLength + 1) * sizeof(char)); // 1 for terminating '\0'
if(NULL != onlyName)
{
//Copy name part.
strncpy(onlyName, name, nameLength);
onlyName[nameLength] = '\0'; //Make onlyName a string
printf("Name: [%s]\n", onlyName);
free(onlyName);
onlyName = NULL;
}
}
}
}
I have assumed that name will be at first place in your input string. Then following small logic will work for you.
void stringEvaluation(char *name){
char *p;
char OutPut[50]={0};
if (strstr(name, "Tall") != NULL)
{
p = strstr(name," ");
p++;
p = strstr(p," ");
strncpy(OutPut,name,(p-name));
printf("name=%s\n",OutPut);
}
}
I am parsing a file in C, line by line. Here is an exemple of what I am trying to do :
I have a line for example :
word word word WORDTOFIND: word1 word2 word word
What I want to do is : When I find the word WORDTOFIND, get the two next words (word1 and word2 in this case) of the line. Is there an easy way to do that in C ? I know about the strstr function, but I don't find a way to get the next two words word1 and word2 after I found the good one.
One approach would be this:
int main(void)
{
char *str = "rated rat cat bat hat";
char *key = "rat ";
char *pointer = NULL;
char nwords = 2;
if ((pointer = strstr(str, key)) != NULL)
{
while (*pointer != ' ') pointer++;
while (nwords >= 0)
{
printf("%c", *pointer);
if (*pointer == ' ') {
nwords--;
} else if (*pointer == '\0') {
exit(0);
}
pointer++;
}
}
}
You can try an aproach like this, using strtok to parse the words at every space. This code also uses malloc and realloc to allocate space for an array of strings, and grows it when needed.
The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
void exit_if_null(void *ptr, const char *msg);
char *stripped_word(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
char line[MAXCHAR];
char *word, *newword;
char **allwords;
int init_size = 8, count = 0, i;
const char *key = "WORDTOFIND";
filename = fopen("files.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error reading file!");
exit(EXIT_FAILURE);
}
allwords = malloc(init_size * sizeof(*allwords));
exit_if_null(allwords, "Initial Allocation");
while (fgets(line, MAXCHAR, filename) != NULL) {
word = strtok(line, " \n");
while (word != NULL) {
if (count == init_size) {
init_size *= 2;
allwords = realloc(allwords, init_size * sizeof(*allwords));
}
allwords[count] = malloc(strlen(word)+1);
exit_if_null(allwords[count], "Initial Allocation");
newword = stripped_word(word);
strcpy(allwords[count], newword);
count++;
word = strtok(NULL, " \n");
free(newword);
}
}
for (i = 0; i < count; i++) {
if (strcmp(key, allwords[i]) == 0) {
printf("Next two words:\n");
printf("%s\n", allwords[i+1]);
printf("%s\n", allwords[i+2]);
}
free(allwords[i]);
allwords[i] = NULL;
}
free(allwords);
allwords = NULL;
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
char
*stripped_word(char *word) {
int i, pos = 0;
char *result;
result = malloc(strlen(word)+1);
exit_if_null(result, "Initial Allocation");
for (i = 0; word[i] != '\0'; i++) {
if (isalpha(word[i]) || isdigit(word[i])) {
result[pos++] = word[i];
}
}
result[pos] = '\0';
return result;
}
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