Passing data from a two-dimensional array to a structure - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct words {
char *mas;
}words;
int main(void) {
FILE *fp=fopen("test.txt", "r");
char str[100];
char arr[100][100];
int k=0;
words_in->mas=malloc(sizeof(char)*sizeof(arr));
char *istr;
printf("\nFile text\n\n");
for (int i = 0; i < 3; i++) {
istr = fgets(str, 100, fp);
printf("%s", istr);
for (char* istr = strtok(str, " .\t\n"); istr; istr = strtok(NULL, " .\t\n")) {
strcpy(arr[k++], istr);
}
}
How do I pass all words written to the two-dimensional array to the structure?
I want my structure to have an array of char pointers, instead of just one pointer. Or a linked list of pointers. Or an array of structs.
And is it possible to somehow dynamically allocate memory for the structure and for arrays?

If you want to prevent two loops and you are ready to sacrifice some memory you can follow this approach
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
typedef struct words {
char **mas;
}words;
int main()
{
FILE *fp=fopen("test.txt", "r");
struct stat statbuf;
fstat(fileno(fp), &statbuf);
long f_size = statbuf.st_size;
words words_in;
words_in.mas = (char**) malloc(sizeof(char*) * f_size); // In worst case each byte is one word.
char fbuf[f_size+1]; // In worst case all bytes form one word ;
long word_count = 0;
while(fscanf(fp,"%s", fbuf) == 1) {
words_in.mas[word_count] = strdup(fbuf);
word_count++;
}
for (long i = 0; i < word_count; i++) {
printf("%s\n",words_in.mas[i]);
}
return 0;
}
INPUT 1
Apple
Bat
Cat
OUTPUT 1
Apple
Bat
Cat
INPUT 2
AppleBatCat
OUTPUT 2
AppleBatCat
INPUT 3
Apple Bat Cat
OUTPUT 3
Apple
Bat
Cat

Related

Add parsed elements from text file to array

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;
}

C - Reading strings from text file into arrays inside a structure

I am trying to read text from a .txt file into arrays of a structure.
This is my code (I have played around with this a heap so apologies if it seems all over the place):
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
int main()
{
int i = 1;
int j = 0;
char temp[4];
struct userStruct { // a struct definition for the users;
char pin[5];
char first[26];
char last[26];
};
struct userStruct userList[10]; // an array of struct user to hold 10 users
struct userStruct * users;
users = &userList;
FILE * filePtr;
filePtr = fopen ("users.txt", "r");
if (filePtr != NULL)
{
fscanf(filePtr, "%s %s %s %s", users[i].pin[j], users[i].first[j], users[i].last[j], temp);
if (strcmp(temp, "\n"))
{
i++;
j++;
}
printf("PIN %s| First %s| Last %s|", users[i].pin[j], users[i].first[j], users[i].last[j]);
fclose(filePtr);
}
else
{
printf("Unable to open users.txt");
}
return 0;
}
The users.txt file contains the text:
1234 John Smith
5678 Barry Cool
Many thanks for the help.
You only want 3 conversion specifiers in the scanf. Try
if( 3 == fscanf(filePtr, "%4s %25s %25s", users[i].pin, users[i].first, users[i].last) ){ ...
The printf is also weird. Try:
printf("PIN %s| First %s| Last %s|", users[i].pin, users[i].first, users[i].last);

array of strings not storing correctly

I'm implementing the ls -R linux command in C and I'm having trouble with the recursion step.
So far I have
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
void lsr(char *directory){
DIR *dir;
dir = opendir(directory);
int size = 0;
struct dirent *d;
char *que[100];
char buf[100];
while((d = readdir(dir)) != NULL){
struct stat statbuff;
if(strcmp(d->d_name,".")== 0 || strcmp(d->d_name,"..")==0){
continue;
}
sprintf(buf, "%s/%s", directory, d->d_name);
stat(buf,&statbuff);
printf(" %s",d->d_name);
printf("\n");
if(S_ISDIR(statbuff.st_mode)){
printf("%s Is a directory\n",buf);
que[size] = buf;
size++;
}
}
int i;
for(i = 0; i < size; i++){
printf("dir: %s\n",que[i]);
}
printf("Are in the queue\n");
//for(i = 0; i < size; i++){
// lsr(que[i]);
//}
closedir(dir);
}
int main(int argc, char *argv[]){
char directory[200];
if(argc ==1){
strcpy(directory,".");
}
else{
strcpy(directory,argv[1]);
}
lsr(directory);
return 0;
}
What im going for is that the function finishes printing all the files in the directory before it recurses into the first directory it found. The only thing i could think of is to store them into a array and then make the call that way.
If anyone could point out why it is that when i loop through the array, its content is wrong or maybe even better, A more practical solution as to how to recurse into directories after the file's names have been printed I would greatly appreciate it!
Here you store the address pointed by buf in que[size].
que[size] = buf;
In the next loop iteration,stat(buf,&statbuff); modifies the content pointed by buf and que[size]
So every slot of you array points to this same address and everytime you modifies this content, you modifies the full array.
I suggest to use strcpy() or to reallocate buf before the stat() call.

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).

c fwrite() writing data only right one of the struct variable?

This function is supposed to get a parameter as the pointer of a file and put all file into the struct anagram, then write it to another file. Right now the data only contains
a.word, but it suppose to containst a.sorted too?
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "anagrams.h"
void buildDB ( const char *const dbFilename )
{
FILE *dict, *anagramsFile;
struct anagram a;
//check if dict and anagram.data are open
errno=0;
dict= fopen(dbFilename, "r");
if(errno!=0) {
perror(dbFilename);
exit(1);
}
errno=0;
anagramsFile = fopen(anagramDB,"wb");
char word[SIZE];
char *pos;
int i=0;
while(fgets(word, SIZE, dict) !=NULL) {
//get ripe of the '\n'
pos=strchr(word, '\n');
*pos = '\0';
strncpy(a.word,word,sizeof(word));
//lowercase word
int j=0;
while (word[j]) {
tolower(word[j]);
j++;
}
/* sort array using qsort functions */
qsort(word,strlen(word), 1, charCompare);
strncpy(a.sorted,word,sizeof(word));
fwrite(&a,1,sizeof(word),anagramsFile);
i++;
}
fclose(dict);
fclose(anagramsFile);
}
data:
char word[SIZE];
...
fwrite(&a,1,sizeof(word),anagramsFile);
sizeof(word) returns the full size of the buffer, so you're writing the full length of the buffer each time. You'll want to use strlen() or similar to only write the part of the buffer you're actually using.

Resources