Issues with string in structure in C codig - c

I have some issues with strings in structure, i think that the problem is strcpy(), but i can't resolve it. My exercise says that i have to write a program that prints the distinct words given as input, sorted in order of frequency of decreasing occurrence and precede each word with its number of occurrences. I thought that scanf could do something wrong so i used fgets() to stdin to take my string from input, but it didnt resolve my problem :(. Here is my code (i haven't yet written the function that prints the words in order of frequency).
/*
Write a program that prints the distinct words given as input, sorted in order of frequency of
decreasing occurrence. Precede each word with its number of occurrences.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define SIZE 30
#define MAXWORD 5
typedef struct word_dictionary{
char ww[SIZE];
int occ;
} word;
int is_in_bucket(char *str, word data[]){
int j;
for(j=0;j<MAXWORD;j++){
if( strcmp(str,data[j].ww) == 0)
return 1;
}
return 0;
}
void print_bucket(word data[]) {
int i;
for(i=0;i<MAXWORD;i++){
printf("{%d, %s} ", data[i].occ, data[i].ww);
}
printf("\n");
}
void main( int argc, char **argv) {
word bucket[MAXWORD];
char aux[SIZE];
int i;
int x;
int cond;
for(i=0;i<MAXWORD;i++) {
printf("Insert the word you want to save in the data structure: ");
scanf("%s",aux);
cond = is_in_bucket(aux,bucket);
if(cond == 1) {
bucket[i].occ = bucket[i].occ + 1;
memset(aux,0,SIZE);
} else {
strcpy(bucket[i].ww, aux);
bucket[i].occ = 1;
memset(aux,0,SIZE);
}
}
print_bucket(bucket);
// print_occurrences();
return;
}
My terminal output is:
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: cat
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: mouse
{1, dog} {1, cat} {-1768437999, } {1, V} {1, mouse}
My expected terminal output should be:
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: cat
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: dog
Insert the word you want to save in the data structure: mouse
{3, dog} {1, cat} {1, mouse}

For starters the function main shall have the return type int
int main( int argc, char **argv)
As the function parameters are not used then it is better to declare the function like
int main( void )
The function is_in_bucket does not take into account the number of actual initialized elements in the array bucket. You need to pass this number to the function.
If a word is already present in the array it is not mean that it is stored exactly in the i-th element of the array.
cond = is_in_bucket(aux,bucket);
if(cond == 1){
bucket[i].occ = bucket[i].occ + 1;
memset(aux,0,SIZE);
You need to return form the function is_in_bucket the index of already initialized element or for example -1 otherwise.
Also the function print_bucket shall take into account the actual number of filled elements of the array bucket.

Related

How do I assign a struct array element to a temporary variable in C?

I have this testing code:
#include <stdio.h>
// Create struct
struct test
{
int age;
};
// Create an array holding struct
struct test test_array[10];
int no_test = 0;
int main(int argc, char const *argv[])
{
int i;
// Take multiple inputs to assign to variables in struct
while(no_test < 5)
{
// Create a temp struct instance to hold the current struct array element
struct test temp = test_array[no_test];
// Take input and feed it into the struct age
scanf("%i", &temp.age);
no_test++;
}
// Loop throgh struct and print out its values
for (i = 0; i < no_test; i++){
printf("Age: %i\n", test_array[i]);
}
}
Currently, when I run this and input random 5 integers, the final print loop prints out age=0 for all the elements in the array.
If I remove the struct test temp = test_array[no_test]; line and point the scanf to test_array[no_test] instead, it works as expected, i.e the print loop prints the same values that were entered.
Is it possible to assign the line: test_array[no_test] to a variable (like a placeholder) as I will be using it a lot and I don't want to have to type it in every time.
Thanks.

C function returning different values while calling from main function

I have written a program which read values from a the file. The data in the file is in following format.
100 Full Name SomeDetails.
234 Full Name SomeDetails
Following is the program which i wrote.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 10
struct student
{
int rollno;
char name[20];
char course[25];
};
int main()
{
FILE *fptr;
fptr=fopen("records.txt","r");
struct student s[10];
int i=0,tstudent=0;
char che;
char line[100];
//SECTION : 1.1 -> READING NUMBER OF LINES
while(!feof(fptr))
{
che=fgetc(fptr);
if(che=='\n')
{
tstudent++;
}
}
printf("Total Lines in File = %d\n",tstudent);
fclose(fptr);
//SECTION : 1.2 -> READING RECORDS FROM FILE
fptr=fopen("records.txt","r");
char newString[20][20];
int ii,j,ctr;
j=0;
ctr=0;
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(ii=0; ii<=(strlen(line)); ii++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[ii]=='\t'||line[ii]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[ii];
j++;
}
}
}
for(ii=0; ii < ctr; ii++)
{
printf("\n%s",newString[ii]);
}
printf("Value of ctr = %d",ctr);
fclose(fptr);
}
Above code is working fine, BUT all the code is in main function, but i want to make a separate function which can be called from main file and return me every data of file in two dimensional or one dimensional array as return value.
Any help/suggestions would be appreciated.
I tried following CODE as a separate function.. NOT WORKING.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char readfile(int tstudent,FILE* filename)
{
//FUNCTION TO READ RECORDS FROM FILE.
FILE *fptr;
int i,k;
char line[100];
char newString[20][20];
int j=0,ctr=0;
fptr=fopen("records.txt","r");
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(k=0; k<=(strlen(line)); k++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[k]=='\t'||line[k]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[k];
j++;
}
}
}
return newString;
}
I defined a new variable char results[] in main function.. and tried to called the function as follows
results[]=readfile(tstudent,fptr)
but when trying to read results.. its showing garbage
char readfile(int tstudent,FILE* filename)
...
char newString[20][20];
...
return newString;
That can't be a good thing, right? You define readFile to return one single character (not a pointer, just one byte) and then return an array instead. We should not be surprised the compiler complained.
If you "fix" that be redefining the return type, you still have a problem because newString is an automatic local variable. The storage (memory) it defines is undefined outside the function.
The easiest way for a function to populate a structure (or array) in C is for the caller to pass it as a function parameter. So you wind up with something more like:
int readfile( FILE* input, char newString[][20], int tstudent )
where newString is defined the same way as you have it, but by the caller, not in readfile. Cf. the stdio functions like fgets; most of them require the caller to define the buffer they read into.
I'll just point out a few more mistakes.
Whenever you call a function -- especially an I/O function -- check for errors. You may want to read tstudent records, but how many are there? If you ask for 5 and find only 1, what then? Your read loop must test for end-of-file, and readfile must return the number of records read, else the caller will never know. Compare with how fread(3) works. Those Unix guys knew a thing or two about how to define a function!
Now your function looks something like this:
int readfile( FILE* input, char newString[][20], int tstudent ) {
char line[100], *s;
int i=0;
for( ; i < tstudent && (s = fgets(line, sizeof(line), input)) != NULL; i++ ) {
/* do stuff with line */
}
/* check for EOF/error if s is NULL, and report */
return i;
}

Creating an array with unknown size of input files

I newer in C language. I could not solve my problem. I have a input file, let's say input.txt. We know there are 4 column on every line. Nevertheless, we do not know how many lines are there. I give you sample input.txt:
Student,James,12,65
Teacher,Jane,23,60
Teacher,Michael,30,75
Student,Erric,15,73
First column can be 2 different things like student or teacher. 2nd column will be unique. No repeated names. 3rd column will be ages of the person's. 4th column will be weights. Also, I am trying to make 2D array. So, my goal is:
arrName = {{Student, James, 12, 65}, {Teacher,Jane,23,60}, {Teacher,Michael,30,75}, {Student, Erric, 15,73}}
I am trying to create like this array. The array must be dynamically. because we do not know how many lines are there. I could not split the every line by commas. I have tried strdot. how can I parse the lines with comma, and add them into 2D array? Also, I got confused about pointers. While creating 2D array, do we have to use like char **arrPtr;? Or using like *arrPtr is enough for creating 2D array?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COLUMN 4 //We know that there are 4 column in chars.txt file.
int main(int argc, char const *argv[]) {
char *arrName;
int nameLines;
arrName = (char *) malloc( sizeof( char ) );
FILE *FileName;
FileName = fopen(argv[1], "r");
if (FileName == NULL) {
printf("The Name file could not open!\n");
exit(0);
}
else{
char c;
while ( (c == fgetc(FileName)) != EOF ) {
if (c == '\n') {
nameLines++;
}
}
printf("%d\n", nameLines);
}
return 0;
}
I could not continue after else statement. Can you help me?
You got a bunch of errors in your code like this for example.
while ( (c == fgetc(FileName)) != EOF ) { -> Comparison of constant -1 with boolean expression is always true
So let's start fresh. This is how I would read a comma separated file and dynamically allocate memory to an array of ´read´ objects. It's actually less lines of code then you would expect.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COLUMNS 4
#define MAX_STRING_LENGTH 100 //Enter the maximum characters allowed as profession and name
typedef struct theDAta{
char type[MAX_STRING_LENGTH+1];
char name[MAX_STRING_LENGTH+1];
unsigned int age;
unsigned int weight;
}theData;
int main(int argc, char const *argv[]) {
theData* allDataPtr=malloc(1); //Pointer to all entries
theData currentData; //The current read data
int currentBlock=0; //the index currently 'active'
FILE *fp = fopen(argv[1], "r");
if (!fp) {
printf("The file you provided can't be read!\n");
exit(EXIT_FAILURE);
}
while (fscanf(fp, "%[^,],%[^,],%d,%d\n", currentData.type, currentData.name,&currentData.age,&currentData.weight) == COLUMNS) {
allDataPtr=realloc(allDataPtr, sizeof(theData)*(currentBlock+1));
if (!allDataPtr) {exit(EXIT_FAILURE);} //Memory allocation failure. Ok so here i lost my pointer to the previous memory.. However we let the OS garbage collect us.
memcpy(allDataPtr+currentBlock++, &currentData, sizeof(currentData));
}
for (int x=0; x<currentBlock; x++) {
printf("Profession: %s\nName: %s\nAge: %d\nWeight: %d\n\n",allDataPtr[x].type,allDataPtr[x].name,allDataPtr[x].age,allDataPtr[x].weight);
}
fclose(fp);
free(allDataPtr);
return 0;
}
So what I do is to create a struct containing the stuff I want to populate from the file. Then I populate that object and extend the memory with the size of that object and then copy the read data to the end of that memory block.. That's basically it... Hope you get great grades :) !!
/Anders
EDIT
Was a bit bored this evening, so let's shave the code... And humm, well. This is not part of my official answer :-) but you could bling it like this (it's actually also skipping one layer of memory copy :) and the engine is 3 lines of C code if you define a line of C code delimiter as ';'->
typedef struct j{
char t[MAX_STRING_LENGTH+1];
char n[MAX_STRING_LENGTH+1];
unsigned int a;
unsigned int w;
}j;
int main(int argc, char const *argv[]) {
j* g;
int l=0;
FILE *h;
if((!(h=fopen(argv[1],"r"))||(!(g=malloc(sizeof(j))))))exit(-1);
while(fscanf(h,"%[^,],%[^,],%d,%d\n",g[l].t,g[l].n,&g[l].a,&g[l].w)==COLUMNS)if(!(g=realloc(g,sizeof(j)*(++l+1))))exit(-1);
for(int x=0;x<l;x++)printf("Profession: %s\nName: %s\nAge: %d\nWeight: %d\n\n",g[x].t,g[x].n,g[x].a,g[x].w);
fclose(h);
free(g);
return 0;
}

How to reset allocated memory and resources in c?

My program consists of a Menu, where you can select 1 of 2 options.
The second is just to exit the program. The first, however, is where you can find a specific sequence of bits that you choose, in a separate ".txt" file with 100.000 lines.
It does what I want the first time, and then returns to the Menu.
The problem is when the user goes for a second (or more) search. The program prints on screen random information.
It seems like I didn't do a "reset" of the resources, memory or values on the first search.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char ID[8];
char content[2048];
int distance;
} DATA;
void search(){
FILE *f;
DADO *z=NULL;
long int tot=0;
int a;
int c;
int i;
int j=1;
int k=0;
char e;
char b[2048];
printf("\n");
f=fopen("DANGER_DB_LARGE.txt", "r");
printf("\n");
printf("How many results do you wish?\n");
scanf("%d",&a);
printf("Introduce the sequence:\n");
scanf("%s",b);
c=strlen(b);
printf("\n");
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
while(e!=EOF){
e=fgetc(f);
if(k<8){
z[tot-1].ID[k]=e;
}
else if(k==8 && e=='\t'){
continue;
}
else if(k>=9 && e!='\n'){
z[tot-1].content[k-9]=e;
}
else if(e=='\n'){
k=(-1);
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
}
k++;
}
for(i=1; i<=tot; i++){
distance(z,i,c,b);
}
free(z);
fclose(f);
}
I proceed to store the ID and content of every single one of those 100.000 lines of text. I end the function by doing free(z), but when I search again the program just prints random stuff.
Use of uninitialised variables without an intervening assignment is undefined behaviour. It may work on the first Wednesday of every month, on the first time through the loop, only when the boss is looking, ...
int e; // originally was char
//...
while (e != EOF) { // uninitialised, no intervening assignment
Realloc returns void by the way
void *realloc(void *ptr, size_t size)
plus it takes a pointer as input so its pass by reference.
update: This function returns a pointer to the newly allocated memory, or NULL if the request fails.
my bad.

use strtok to track of the frequency of each word in a text,but code cannot be executed,

I'm trying to use array of structure and strtok to track of the frequency of each word in a text. Every time a word is added for the first time to the array set count to 1. If the same word appears again, increment the count. But code can not be executed, the compile passed with out any error and warning. I don't know how to debug the code. the code is shown below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char word[32];
int count;
}Entry;
int main(void) {
int n=0;
Entry entry[n];
char s[]="C (pronounced like the letter C) is a general programming language";
char *delim=" ; ( ) . , \n";
char *p;
p=strtok(s, delim);
printf("%s\n",p);
strcpy(entry[0].word, p);
entry[0].count=1;
while((p!=NULL)){
/*printf("%s",p);*/
while (n<10){
p=strtok(NULL, delim);
if(p==entry[n].word){
entry[n].count++;
}
else{
strcpy(entry[n+1].word, p);
entry[n+1].count=1;
}
n++;
}
}
return 1;
}
if(p==entry[n].word){
You can't compare strings using ==, change to
if(strcmp(p, entry[n].word) == 0)){
And you are reserving space for 0 elements:
int n=0;
Entry entry[n];

Resources