Use strings from a function to main function - c

One of my functions reads lines from a text file and stores into a variable. I need a way to use that variable in my main function. I've tried several methods and nothing has worked. Can anyone help me?
#include <stdio.h>
#include <string.h>
int test(const char *fname, char **names){
char usernames[250][50];
FILE *infile;
char buffer[BUFSIZ];
int i =0;
infile = fopen(fname, "r");
while(fgets(buffer,50,infile)){
strcpy(usernames[i],buffer);
printf("%s",usernames[i]);
i++;
}
int x, y;
for(y = 0; y < 250; y++)
for(x = 0; x < 50; x++)
usernames[y][x] = names[y][x];
return 0;
}
int main()
{
char *names;
test("test.txt", &names);
}
Can anyone help? I haven't coded in C in a long time.

In C, the caller should allocate the memory for the strings it needs, otherwise, no one knows who's supposed to free memory. Then you can pass a pointer to a function that will populate it.
int main() {
char names[250][50];
test("test.txt", names);
for (int i=0; i < 50; i++) {
printf("File %d: %s", i, names[i], 250);
}
}
void test(const char *fname, char(*names)[50], int maxWords){
FILE *infile;
int i =0;
char buffer[50];
infile = fopen(fname, "r");
while(fgets(buffer,50,infile) && i < maxWords){
strcpy(usernames[i],names[i]);
i++;
}
}

Related

fscanf always returns 0(CLOSED)

I am a beginner in C programming, and I am trying to write a simple code to read a text file and write its content into an array, then print it on console. However, I always get 0.0000, and I could not solve the problem.
#include <stdio.h>
#include <stdlib.h>
int numOfLines(FILE *fp1);
void printarr(float arr[], int size);
float *filetoArr(FILE *fp, int arrsize);
int main(int argc, const char *argv[]) {
char *fileName1 = argv[1];
FILE *fp1 = fopen(fileName1, "r");
printf("File name: %s", fileName1);
int size = numOfLines(fp1);
printf("Number of lines in the file: %d\n", size);
float *arr = filetoArr(fp1, size);
printarr(arr, size);
free(arr);
fclose(fp1);
}
void printarr(float *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%f ", *(arr + i));
}
}
float *filetoArr(FILE *fp, int arrsize) {
int size = arrsize;
float *arr = (float *)malloc(sizeof(float) * size);
for (int i = 0; i < size; i++) {
fscanf(fp, "%f\n", (arr+i));
}
return (arr);
}
int numOfLines(FILE *fp1) {
int numberOfLines = 0;
char c;
do {
c = getc(fp1);
if (c == '\n') {
numberOfLines++;
}
} while (c != EOF);
return numberOfLines;
}
your numOfLines goes to the end of the file.
You have to rewind(fp1) to reset your file handle to position 0, or fscanf hits the end of the file, and doesn't read anything (check return code from fscanf: it should be 1 I bet you're getting 0 all the time)
There are multiple problems in your code:
you read the whole file in numOfLines(): you must reset the file pointer to the beginning of file with rewind(fp1); so fscanf() can read the file instead of hitting the end of file immediately.
the variable c used to read bytes from the file must be defined as an int for the test for end of file to be reliable. Otherwise, depending on whether char is signed or not by default, the EOF would never match or could potentially match the character \377 as end of file erroneously.
you do not check for failure to open the file.
Although returning 0 is implicit for function main() since C99, it is advisable to write the return 0; statement explicitly for better clarity.

dynamic memory reading from a file

I desperately need some help with an exercise my professor gave me. Essentially, I'm making a program using a structure and dynamic memory where it'll read a file where each line has one word, and it'll print to a new file each unique word and how many times it was in the file.
So for instance, if the file going in had this
apple
orange
orange
The file it prints to would say
apple 1
orange 2
So far, this is my code
#include <stdio.h>
#include <stdlib.h>
struct wordfreq {
int count;
char *word;
};
int main(int argc, char *argv[]){
int i;
char *temp;
FILE *from, *to;
from = fopen("argc[1]","r");
to = fopen("argv[1]","w");
struct wordfreq w1[1000];
struct wordfreq *w1ptr[1000];
for(i = 0; i < 1000; i++)
w1ptr[i] = NULL;
for(i = 0; i < 1000; i++)
w1ptr[i] = (struct wordfreq*)malloc(sizeof(struct wordfreq));
while(fscanf(from,"%256s",temp)>0){
}
for(i = 999; i >= 0; i--)
free(w1ptr[i]);
}
w1ptr should store a word from the file in the wordfreq file, then increment count in that array. I have no clue how to go about storing the word in *word though. Any help would be greatly appreciated
This is how in general your read/write from a file
const int maxString = 1024; // put this before the main
const char * fn = "test.file"; // file name
const char * str = "This is a literal C-string.\n";
// create/write the file
puts("writing file\n");
FILE * fw = fopen(fn, "w");
for(int i = 0; i < 5; i++) {
fputs(str, fw);
}
fclose(fw);
puts("done.");
// read the file
printf("reading file\n");
char buf[maxString];
FILE * fr = fopen(fn, "r");
while(fgets(buf, maxString, fr)) {
fputs(buf, stdout);
}
fclose(fr);
remove(fn); // to delete a file
puts("done.\n");

Reading and writing from files with a new form

I'm trying to read from a file and I have to use a new form of it I'm not really certain how to use. I've posted the code below of what function I have and I'm not sure what to do about this error and how to fix it?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
double* read_file(FILE* file, int length);
int main(int argc, char* argv[])
{
double* array = malloc(10 * sizeof(double));
int length = atoi(*(argv + 1));
FILE* file = *(argv + 2);
if (argc < 4 || argc > 4)
{
printf("Insufficient arguments. Check your command line.\n");
return 0;
}
array = read_file(file, length);
printf("%p", array);
return 0;
}
double* read_file (FILE* file, int length)
{
FILE* ptr;
double* array = malloc(length * sizeof(double));
int i = 0;
if ((ptr = fopen(file, "r")) == NULL)
{
return 0;
}
else
{
for (i = 0; i < length; i++)
{
fscanf(ptr, "%lf", (array + i));
}
}
fclose(ptr);
return array;
}
First of all, you're trying to assign a char string to a variable of type pointer to FILE. The compiler won't let you do that.
// not allowed
FILE* file = *(argv + 2);
Secondly, you're passing a pointer to FILE to fopen(), but fopen() expects it's first argument to be a char string so that won't work either.
// file is FILE*, not allowed
ptr = fopen(file, "r"));
If you fix those two lines the code should compile.
fix like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//double* read_file(FILE* file, int length);
//You do not need to pass a file pointer, you need a file name.
//It opens the file within this function
double *read_file(const char *filename, int length);
int main(int argc, char* argv[]){
//if (argc < 4 || argc > 4)
//argc < 4 || argc > 4 same as argc != 4
//It is thought that it is 3 because only argv[1] and argv[2] are used.
//It is necessary to check arguments before using them.
if (argc != 3) {
printf("Usage : %s number_of_elements file_name\n", argv[0]);
printf("Insufficient arguments. Check your command line.\n");
return 0;
}
//double* array = malloc(10 * sizeof(double));//It is not necessary as it is secured by read_file. Make memory leak.
int length = atoi(argv[1]);
const char *file = argv[2];
double *array = read_file(file, length);
if(array != NULL){
for(int i = 0; i < length; ++i)
printf("%f\n", array[i]);
free(array);
}
return 0;
}
double* read_file (const char *file, int length){
FILE *ptr;
if ((ptr = fopen(file, "r")) == NULL){
return NULL;
}
//It causes a memory leak unless you first confirm that the file can be opened
double *array = malloc(length * sizeof(double));
for (int i = 0; i < length; i++){
if(1 != fscanf(ptr, "%lf", array + i)){
printf("Failed to read the %ith element.\n", i+1);
break;
}
}
fclose(ptr);
return array;
}

Unexpected Segfault - What am I doing wrong

I've been trying to blow the cobwebs off my C programming skills, and I've been getting an error I can't seem to figure out. This program reads in a list of integers separated by newlines. This bit happens in read_integer_file... I have no issues going through the input there. It's when I pass the data back to main via out that I have the problem.
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int* out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%i\n");
num_lines++;
}
/* seek to the beginning of the file*/
rewind(file);
out = malloc(sizeof(int)*num_lines);
if(out == NULL)
return 0;
int inp = 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%i\n", &inp);
out[i] = inp;
printf("%i\n", out[i]); /* <---- Prints fine here! */
i++;
}
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int* numbers = NULL;
int number_count = read_integer_file(array_filename, numbers);
for(int i = 0; i < number_count; i++)
{
/* Segfault HERE */
printf("%i\n", numbers[i]);
}
}
You have not allocated any memory for numbers. Currently it is pointing to no where. When it gets back to the calling function it is still pointed to nowhere. Pass a pointer to a pointer to the function to allocate it within the function.
int read_integer_file(char* filename, int** out)
{
...
*out = malloc(sizeof(int)*num_lines);
...
int number_count = read_integer_file(array_filename, &numbers);
This is a version of your code working.. Keep in mind also that fscanf just skip the \n the way you wrote it so it's like writing fscanf(file, "%d");
And if you don't put a variable to handle what it reads the compiler may not see it but you'll probably get an error..
So here is the code :
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int **out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
int garbi;
char garbc;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%d", &garbi);
fscanf(file, "%c", &garbc);
if (garbc=='\n') ++num_lines;
}
/* seek to the beginning of the file*/
rewind(file);
int *nbr = malloc(sizeof(int)*num_lines);
if(nbr == NULL)
return 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%d", &nbr[i++]);
fscanf(file, "%c", &garbc);
}
*out=nbr;
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int *numbers = NULL;
int number_count = read_integer_file(array_filename, &numbers);
int i;
for(i = 0; i < number_count; ++i)
printf("%d\n", numbers[i]);
return 0;
}

Opening files with sequential filenames

For an assignment I'm trying to output multiple files with different names e.g. file_1.dat, file_2.dat etc. I was hoping I could do this the same way as fprintf and fscanf but that doesn't work.
What would anyone suggest (code below is what I used)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
for( i = 0; i < 3; i++)
{
FILE *file;
file = fopen("testing_%d.dat", i,"w");
}
}
sprintf should come in handy.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
for( i = 0; i < 3; i++)
{
char buf[100]
FILE *file;
sprintf(buf, "testing_%d.dat", i);
file = fopen(buf, "w");
}
}
You can first write the file name to a char [] by using sprintf(), and then pass it to fopen().
char myFile[200];
sprintf(myFile, "testing_%d.dat", i);
file = fopen(myFile, "w");
file should be an array of FILE *. Also, fopen doesn't format a string like printf. Change your file opening logic to something like this:
#define NUM_FILES (3)
#define FILE_NAME_LENGTH (100)
FILE *pFileArr[NUM_FILES];
char filename[FILE_NAME_LENGTH];
for(i = 0; i < NUM_FILES; i++)
{
snprintf(filename, FILE_NAME_LENGTH, "testing_%d.dat", i);
pFileArr[i] = fopen(filename, "w");
}

Resources