Reputation: 378
Recently i was practicing FILE handling in C, thus i wrote a program which read the file character by character and store the output as string(very long). My file contain various names separated by tab, one line has 3 names as follows.
Name1 Name2 Name3
Name4 Name5 Name6
Name7 Name8 Name9
As a result of function i wrote, now i have a string[Name1 Name2 Name3 Name4 Name5 Name6 ....]
Now I want to store these names into a structure.. I have written following function for it.
#include<stdio.h>
#include<stdlib.h>
#define MAX_LENGTH 30
struct sarray
{
char data[MAX_LENGTH]
};
char* stringtoarray(char longstring[],int totalchar,int totaldata)
{
int i=0,j=0;
char che;
struct sarray say[totaldata];
char* resultptr;
che=longstring[i];
while(che!='NULL')
{
if(che=='\t' || che=='\n')
{
j++;
i=0;
}
else
{
say[j].data[i]=che;
i++;
}
che=longstring[i];
}
resultptr=&say->data;
return resultptr;
}
Following are the arguments to function.
I tried to call the above function from main function, but it is not showing any results, although no error during compilation.
Any help would be appreciated.
Upvotes: 1
Views: 2020
Reputation: 13144
You could do yourself a big favour by reading the format you want in the first place instead of single characters:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR(X) #X
#define STRINGIFY(X) STR(X)
#define MAX_TOKEN_LENGTH 30
#define TOKENS_GROWTH 3
typedef struct token_tag {
char data[MAX_TOKEN_LENGTH + 1];
} token_t;
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
char token[MAX_TOKEN_LENGTH + 1];
size_t tokens_size = 0;
size_t num_tokens = 0;
token_t *tokens = NULL;
while (fscanf(input, "%" STRINGIFY(MAX_TOKEN_LENGTH) "s", token) == 1) {
if (num_tokens == tokens_size) {
token_t *tmp_tokens = realloc(tokens, (tokens_size + TOKENS_GROWTH) * sizeof(*tmp_tokens));
if (!tmp_tokens) {
fputs("Not enough memory :(\n\n", stderr);
break;
}
tokens_size += TOKENS_GROWTH;
tokens = tmp_tokens;
}
memcpy(tokens[num_tokens++].data, token, MAX_TOKEN_LENGTH + 1);
}
fclose(input);
for (size_t i = 0; i < num_tokens; ++i)
printf("Token #%02zu: \"%s\"\n", i + 1, tokens[i].data);
free(tokens);
}
Token #01: "Name1"
Token #02: "Name2"
Token #03: "Name3"
Token #04: "Name4"
Token #05: "Name5"
Token #06: "Name6"
Token #07: "Name7"
Token #08: "Name8"
Token #09: "Name9"
Upvotes: 2
Reputation: 11567
There are any problems with your code.
1/ As already mentioned, you are returning a pointer to locally allocated data. When you declare a local struct/array in a func, space to hold the struct is allocated in the stack and is "lost" when you leave the func. So the returned pointer will point to garbage.
The only way is to allocate the data in the heap with malloc.
replace struct sarray say[totaldata];
by
struct sarray *say;
say = (struct sarray *) malloc(totaldata * sizeof(struct sarray));
2/ NULL is not a char. If you want to test the end of your input string replace while(che != 'NULL')
with while(che != '\0')
3/ returning &say->data is incorrect. If you want to get all information, just return a pointer to your array of structs (and change the declaration of the func).
4/ Many sanity checks are missing
5/ why do you have an unused parameter in your func (totalchar)
6/ and you should rethink your algorithm, for instance using scanf as already indicated.
Upvotes: 1