Add parsed elements from text file to array - c

I am trying to write a code that fetches lines from a txt file and adds parsed out variables from those lines to an array. The txt file reading and the parsing works perfectly.
My text file "inventory.txt" looks like this:
Mars;6
Snickers;7
Bounty;2
Twix;4
MilkyWay;6
KitKat;8
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
//INITIALIZE
char line[100];
char *elements[100] = {};
int i_stock[100];
int r2 = 0;
char item[20] = {0};
int stock;
//DEFINE FILE
FILE *the_file = fopen("inventory.txt","r");
//CHECK IF FILE EXISTS
if(the_file == NULL) {
perror("Inventarfehler");
exit(1);
}
//SCAN LINES FOR STOCK
while(fgets(line, sizeof(line), the_file)) {
sscanf(line, "%[a-zA-Z];%d", &item, &stock);
//ADD VAR TO ARRAY
elements[r2] = item;
r2++;
}
printf(elements[2]);
return 0;
}
Whatever index of elements I print, it is always KitKat. My code keeps overwriting the variables.
printf("%s",elements[2]) should print out Bounty.
Could anyone help me solve this?
Thanks in advance!

The problem is that all of your elements are simple references to item whose content will ultimately be the last candy bar name you read.
Here is one way to solve this problem, by copying each parsed string to a newly-allocated string on the heap using strdup():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COUNT 100
int main()
{
//INITIALIZE
char line[MAX_COUNT];
char *elements[MAX_COUNT] = {};
int i_stock[MAX_COUNT];
int r2 = 0;
char item[20] = {0};
int stock;
//DEFINE FILE
FILE *the_file = fopen("inventory.txt", "r");
//CHECK IF FILE EXISTS
if (the_file == NULL)
{
perror("Inventarfehler");
exit(1);
}
//SCAN LINES FOR STOCK
while (r2 < MAX_COUNT && fgets(line, sizeof(line), the_file))
{
sscanf(line, "%[a-zA-Z];%d", item, &stock);
//ADD VAR TO ARRAY
elements[r2] = strdup(item);
r2++;
}
printf("%s\n", elements[2]);
// Free allocated memory
for (int ii = 0; ii < r2; ii++)
{
// printf("Free elements[%d]: %s\n", ii, elements[ii]);
free(elements[ii]);
elements[ii] = NULL;
}
return 0;
}

Related

string of undetermined length c

Hi I was trying to create an array of string of an undetermined length in c.
This is my code :
int main()
{
int lineCount=linesCount();
char text[lineCount][10];
printf("%d",lineCount);
FILE * fpointer = fopen("test.txt","r");
fgets(text,10,fpointer);
fclose(fpointer);
printf("%s",text);
return 0;
}
I would like to replace 10 in
char text[lineCount][10];
My code reads out a file I already made the amount of lines dynamic.
Since the line length is unpredictable I would like to replace 10 by a something dynamic.
Thanks in advance.
To do this cleanly, we want a char * array rather than an 2D char array:
char *text[lineCount];
And, we need to use memory from the heap to store the individual lines.
Also, don't "hardwire" so called "magic" numbers like 10. Use an enum or #define (e.g) #define MAXWID 10. Note that with the solution below, we obviate the need for using the magic number at all.
Also, note the use of sizeof(buf) below instead of a magic number.
And, we want [separate] loops when reading and printing.
Anyway, here's the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
linesCount(void)
{
return 23;
}
int
main(void)
{
int lineCount = linesCount();
char *text[lineCount];
char buf[10000];
printf("%d", lineCount);
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// store line -- we must allocate this
text[i++] = strdup(buf);
}
fclose(fpointer);
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
return 0;
}
UPDATE:
The above code is derived from your original code. But, it assumes that the linesCount function can predict the number of lines. And, it doesn't check against overflow of the fixed length text array.
Here is a more generalized version that will allow an arbitrary number of lines with varying line lengths:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int lineCount = 0;
char **text = NULL;
char buf[10000];
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
++lineCount;
// increase number of lines in array
text = realloc(text,sizeof(*text) * lineCount);
if (text == NULL) {
perror("realloc");
exit(1);
}
// store line -- we must allocate this
text[lineCount - 1] = strdup(buf);
}
fclose(fpointer);
// print the lines
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
// more processing ...
// free the lines
for (i = 0; i < lineCount; ++i)
free(text[i]);
// free the list of lines
free(text);
return 0;
}

removing string array words from a txt file

I am trying to remove particular words from a file and print the other words but the code is not doing what it is supposed to do I have debugged like crazy and the answers don't make sense I find it hard to understand why it's doing it like this?
NB all the word in the original out1.data.txt file are on separate lines
Bellow is my code:
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int
main(void)
{
FILE *inp;
FILE *outp;
int i, found;
char word[16];
char toremove[][5] = {"is\n", "a\n", "and\n", "with\n", "By\n", "that\n", "to\n", "It\n", "has\n", "in\n", "for\n", "from\n"};
inp = fopen("out1.dat.txt", "r");
outp = fopen("out2.dat.txt", "w");
while(!feof(inp))
{
for(i = 0; i < 13; i++)
{
printf("%s", toremove[i]);
found = 0;
fgets(word, 16, inp);
if(strcmp(word, toremove[i]) == 0)
{
printf("%d", strcmp(word, toremove[i]));
found = 1;
}
else
{
i = 14; // had to set it to outside it parameters if found
}
if(found != 1)
{
printf("%s", word);
printf("%d ", strcmp(word, toremove[i]));
}
}
}
fclose(inp);
fclose(outp);
return(0);
}
There were a few issues in your code. I've made the fixes and added the comments with !.
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
FILE *inp;
FILE *outp;
int i, found;
char word[16];
// !The length of the longest string is 6: [ with\n\0 ].
// !You have to take null character into account
char toremove[][6] = {"is\n", "a\n", "and\n", "with\n", "By\n", "that\n", "to\n", "It\n", "has\n", "in\n", "for\n", "from\n"};
inp = fopen("out1.dat.txt", "r");
outp = fopen("out2.dat.txt", "w");
while (!feof(inp))
{
fgets(word, 16, inp);
int toremoveLen = sizeof(toremove) / sizeof(toremove[0]); // ! Length of the list
for (i = 0; i < toremoveLen; i++)
{
// printf(toremove[i]);
found = 0;
if (strcmp(word, toremove[i]) == 0)
{
printf(strcmp(word, toremove[i]));
found = 1;
break; // !If the word if found, no need to compare it with others
}
}
if (found != 1) // !Print the word only if it does not match with any word in the blacklist
{
printf("%s", word);
// printf(strcmp(word, toremove[i]));
}
}
fclose(inp);
fclose(outp);
return (0);
}
1)Open source file in r (read) mode. Store its reference in a FILE pointer variable say
fPtr.
2)Create and open a temporary file say delete.tmp in w (write) mode. Store its reference in a variable say fTemp.
3)Read word to remove from user in some variable say toRemove.
4)Read a line from source file fPtr and store it in temporary buffer variable.
5)Remove all occurrence of given word from buffer and write buffer to temporary file fTemp.
6)Repeat step 4-5 till end of source file.
7)Close both file fPtr and fTemp.
8)Delete source file using remove() function.
9)Rename temporary file with source file name using rename() function. And we are done.
FOR CODE LINK
I ended up figuring it out my self thank you though and i came up with a more simplified version as shown below:
#include <stdio.h>
#include <string.h>
int
main(void)
{
FILE *inp;
FILE *outp;
int i, j;
char word[16];
char toremove[][6] = {"is\n", "a\n", "and\n", "with\n", "By\n", "that\n", "to\n",
"It\n", "has\n", "in\n", "for\n", "from\n"};
inp = fopen("out1.dat.txt", "r");
outp = fopen("out2.dat.txt", "w");
while(!feof(inp))
{
fgets(word, 16, inp);
for(i = 0; i < 12; i++)
{
j = strcmp(word, toremove[i]);
if(j == 0)
i = 12;
}
if(j != 0)
{
fprintf(outp, "%s", word);
}
}
fclose(inp);
fclose(outp);
return(0);
}

Finding the most frequent character of an input text file

I am trying to read an input txt file from command line and find the most frequent character in that file for a school project. I can open the txt file and print it without an issue with the following code. Also the funcion below freqcount(), works perfectly when I give it a string from the command line. But I can't seem to make them work together. I think I'm messing up something while setting up the dest array down below. Any help would be appreciated.
Also, for non static sized strings, which one is generally better to use, malloc or calloc?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#define DEST_SIZE 26 // An arbitrary size but longest string to work is 24
char freqcount(char * str){
// Construct character count array from the input
// string.
int len = strlen(str);
int max = 0; // Initialize max count
char result; // Initialize result
int count[255] = {0};
// Traversing through the string and maintaining
// the count of each character
for (int i = 0; i < len; i++) {
count[str[i]]++;
if (max < count[str[i]]) {
max = count[str[i]];
result = str[i];
}
}
return result;
}
//////////////////////////////////////////////////////////////////////
int main(int argc,char ** argv){
int i=0;
char dest[DEST_SIZE] = {0};
if(argc !=2){
perror("Error: ");
return -1;
}
FILE * f = fopen(argv[1], "r");
if (f == NULL) {
return -1;
}
int c;
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
char cnt=freqcount(dest);
printf("%c",cnt);
}
return EXIT_SUCCESS;
}
Sorry I forgot to add, originally call was after the loop such as;
(omitted the first part)
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
}
/*int l;
for (l=0; l<DEST_SIZE;l++){
if (dest[i] != 0){
printf("%c\n",dest[l]); // burda da arrayi okuyor ama array 255 long oldugu icin cogu bos
}
}*/
char cnt=freqcount(dest);
printf("%s",cnt);
return EXIT_SUCCESS;
}
when it is like this, the code returns the following with the input "An example Of the input.
An example
Of the input.(null)
Move the call of freqcount to after the while loop:
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
}
dest[i]='\0'; // terminate
char cnt=freqcount(dest);
printf("%c",cnt);

Number of words in n strings read from a file

So i am trying to determine number of words from n strings.The problem I have is that the when I read the number of the strings from the file it somehow count as a string I guess.I am trying to get rid of the first line of the output but can't tell how.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int numar_cuvinte(char *propozitie, char *copie, int numar_propozitii, FILE *f)
{
fgets(propozitie,49,f);
strcpy(copie,propozitie);
char *delimitatori = " ";
char *token = strtok(copie,delimitatori);
int numar_cuvinte = 0;
while(token!=NULL)
{
numar_cuvinte++;
token = strtok(NULL,delimitatori);
}
return numar_cuvinte;
}
int main()
{
FILE *f;
char*name_file = "in.txt";
f=fopen(name_file,"r");
if(f == NULL)
printf("Can't oppen %s",name_file);
int nr_strings;;
fscanf(f,"%d",&nr_strings);
char *propozitie = (char*)malloc(50*sizeof(char));
char *copie = (char*)malloc(50*sizeof(char));
for(int i = 0 ; i <= nr_strings ; i++)
printf("String : %s has %d words \n\n",propozitie,numar_cuvinte(propozitie,copie,nr_strings,f));
free(propozitie);
free(copie);
fclose(f);
return 0;
}

Converting Greek words to uppercase

I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).

Resources