Structures and input from files - c

My text file is as following:
Random Words //this only appears once at the top
Occupation1
1 2 3 4 5
6 7 8 9 10
Occupation2
11 12 13 14 15
16 17 18 19 20
I am having some trouble with the input and was wondering if you could take a look at my code.
typedef struct foo
{
char occupation[256];
int numbers[limita][limitb];
}FOO;
void function(FOO input[]);
int main()
{
FOO input[limit];
function(input);
return 0;
}
void function(FOO input[])
{
FILE* file;
file = fopen("textfile.txt","r");
int a=0; int b =0;
char temp[81];
char randomwords[81];
while(fgets(temp,sizeof(temp)-1,file))
{
sscanf(temp, "%[^\n] %[^\n] %d", randomwords,&input[a].occupation[a], &input[a].numbers[a][b]);
a++;
}
}
So I tried printing out (with printf) the random words and the occupation but to no avail. I don't think i'm using numbers correctly at all as it has to be a 2D array and don't seem to be changing the columns.
I would really appreciate a step in the right direction/some help. Please explain simply. Thank you very much.
EDIT:
technomage brought up an interesting point regarding what i'm doing vs what I want. I'm not sure how to change in reflection to what he suggested though.

You probably want to do something like this. This implementation assumes that there are no blank lines in the input file. There are lot of hard coding here, you may want to make it better. I hope this helps you...
typedef struct foo
{
char occupation[256];
int numbers[2][5];
}FOO;
void function(FOO input[]);
void function(FOO input[])
{
FILE* file;
file = fopen("textfile.txt","r");
int a = 0, count, i;
char temp[81];
char randomwords[81];
if (file == NULL)
{
return;
}
fscanf(file, "%[^\n]\n", randomwords);
printf("%s\n", randomwords);
while (feof(file) != EOF)
{
i = 0;
i = fscanf(file, "%[^\n]\n", input[a].occupation);
if (i == -1)
break;
for (count=0; count < 5; count++)
{
i = 0;
i = fscanf(file, "%d", &(input[a].numbers[0][count]));
}
for (count=0; count < 5; count++)
{
i = 0;
i = fscanf(file, "%d", &(input[a].numbers[1][count]));
}
a++;
i = 0;
i = fscanf(file, "\n");
if (i == -1)
break;
};
fclose(file);
}
int main(int argc, char *argv[], char *envp[])
{
int i, j, count;
FOO input[10];
function(input);
for (count = 0; count < 2; count++)
{
printf("%s\n", input[count].occupation);
for (i = 0; i < 2 ; i++)
{
for (j = 0 ; j < 5 ; j ++)
{
printf ("%d ", input[count].numbers[i][j]);
}
printf ("\n");
}
printf ("\n");
}
}

Related

Selection sort not working as expected (C language)

I have to sort an array of structs with selection sort, after I read them from a file.txt.
My algorithm is not working as expected, but it always avoid to sort them and it print the struct in decreasing order.
Example of file.txt :
P0 "ANTONIO" 2000 4
P1 "BARTOLOMEO" 1995 6
P2 "CARLO" 2020 1
P3 "DEMETRIO" 1960 2
P4 "ETTORE" 1920 3
P5 "FRANCESCO" 1950 5
Input: 2 5 3 1 6 4
Output: 4 6 1 3 5 2
What am I doing wrong?
Code below:
#include <stdio.h>
#include <stdlib.h>
#define N 7
struct persona
{
char codice[10];
char nome[30];
int anno[10];
int reddito[10];
};
int main()
{
FILE* fp;
fp = fopen("Testo.txt", "r");
struct persona* persona = malloc(sizeof(struct persona) * N);
int i = 0;
int j = 0;
if (fp != NULL)
{
while (i < N-1)
{
fscanf(fp, "%s %s %s %s",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
i++;
}
}
else
{
perror("Errore");
}
fclose(fp);
for(i=0; i<N-2; i++)
{
int min = persona[i].reddito;
for(j=i+1; j<N-1; j++)
{
if(persona[j].reddito < persona[i].reddito)
{
min = persona[j].reddito;
}
persona[N] = persona[j];
persona[j] = persona[i];
persona[i] = persona[N];
}
}
for(i=0; i<N-1;i++)
{
printf("%s\t %s\t %s\t %s\n",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
}
}
You have 6 lines in the file, but you have defined N as 7. It should be updated to 6.
while (i < N-1)
You are reading the first N-2, that is, 5 lines from the file. The 6th line is not being read. Same goes for other loops in the code using N.
int anno[10];
int reddito[10];
You do not need integer array to read the numeric fields in file, an integer should suffice.
As mentioned by #WhozCraig in the comments, the selection sort algorithm is incorrect. Here's the updated code for reference:
#include <stdio.h>
#include <stdlib.h>
#define N 6
typedef struct persona
{
char codice[10];
char nome[30];
int anno;
int reddito;
} PERSONA;
int main()
{
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror("\nFile not found");
exit(1);
}
PERSONA *persona = malloc(sizeof(struct persona) * N);
int i = 0, j;
while (i < N)
{ if (fscanf(fp, "%s %s %d %d", persona[i].codice, persona[i].nome, &persona[i].anno, &persona[i].reddito) == EOF) {
break;
}
i++;
}
fclose(fp);
PERSONA temp;
/* selection sort */
for (i = 0; i < N - 1; i++)
{
int jMin = persona[i].reddito;
for (j = i + 1; j < N; j++)
{
if (persona[j].reddito < persona[jMin].reddito)
{
jMin = j;
}
}
if (jMin != i)
{
temp = persona[i];
persona[i] = persona[jMin];
persona[jMin] = temp;
}
}
for (i = 0; i < N; i++)
{
printf("\n%s\t %s\t %d\t %d", persona[i].codice, persona[i].nome, persona[i].anno, persona[i].reddito);
}
}
Further improvements:
You could also calculate the number of lines in the file in the code instead of relying on a hardcoded value N.
The statement to check sets only the min only if this statement is true
if(persona[j].reddito < persona[i].reddito)
try using the qsort function
int cmpfunc (const void * a, const void * b) {
struct persona *p1 = (struct persona *)a;
struct persona *p2 = (struct persona *)b;
if(p1->reddito < p2->reddito) return -1;
if(p1->reddito > p2->reddito) return 1;
return 0;
}
and instead of the for loop, use
qsort(persona, N, sizeof(struct persona), cmpfunc);

How to make a program that scrambles the order of the words in a sentence from a file

I have a file with say 4 sentences, I know that there are 4 because each sentence has '.' at the end.
What I did was read from the file given and paste each sentence in a 2 dimensional array like so:
char sentence[0][200] = "Hello how are you."
char sentence [1][200] = "I'm good thanks. etc.
Here is the code for this:
int main()
{
char sentence[RSIZ][LSIZ];
char fname[20] = "t.txt";
FILE *fptr = NULL;
int i = 0;
int tot = 0;
char c;
int nrsentences = 0;
printf("\n\n Read the file and store the lines into an array :\n");
printf("------------------------------------------------------\n");
fptr = fopen(fname, "r");
// Check if file exists
if (fptr == NULL)
{
printf("Cant open the file %s", fname);
return 0;
}
// Sentences counter from file
for (c = getc(fptr); c != EOF; c = getc(fptr))
if (c == '.') // Increases if found '.'
nrsentences = nrsentences + 1;
fptr = fopen(fname, "r");
for (i=0; i<nrsentences; i++)
fgets(sentence[i], 200, fptr);
Then I would separate the this array in to words with this code:
(still in main(){})
char newString[10][30];
int j,ctr;
j=0; ctr=0;
for (int k = 0; k < nrsentences; k++) {
for(i=0;i<=(strlen(frases[k]));i++)
{
// if space or NULL found, assign NULL into newString[ctr]
if(sentence[k][i]==' '|| sentence[k][i]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=sentence[k][i];
j++;
}
}
}
printf("\n Strings or words after split by space are :\n");
for(i=0;i < ctr;i++)
printf(" %s ",newString[i]);
Then here is the problem (I think), the part of the scrambling code.
This works like this:
I give the code: the sentences and the inedex.
by default it is like this
index-> 0 1 2 3
sentence-> Hello how are you
but with this code it converts to this:
index-> 3 2 0 1
sentence-> you are Hello how
int index[] = {2,3,5,1,0,4,7,6}; //here I have a function that generates the random list(which I dont know yet how to make it work here
int n = nrsentences;
randomize(newString, index, n, nrsentences);
printf("Reordered array is: \n");
for (int i=0; i<n; i++)
printf ("%s ", newString[i]);
return 0;
}
Here is the randomize() function
void randomize(char* arr[], int index[], int n, int nrsentences)
{
printf("%d", n);
char* temp[n];
// arr[i] should be present at index[i] index
//for (int k = 0; k < nrsentences; k++){
for (int i=0; i<n; i++)
temp[index[i]] = arr[i];
// Copy temp[] to arr[]
for (int i=0; i<n; i++)
{
arr[i] = temp[i];
index[i] = i;
}
//}
}
And here is the index randomizer, which I dont know yet (didnt try) how to add it to the main, or randomize function.
int *random_number(int words)
{
int array[25];
int x, p, count;
int i=0;
srand(time(NULL));
while(i< words){
int r=rand()% words +1;
for (x = 0; x < i; x++)
{
if(array[x]==r){
break;
}
}
if(x==i){
array[i++]=r;
}
}
for(p=0;p<words;p++){
printf("%d ", array[p]);
}
return array;
}
or
int array[25];
int words = 5;
int x, p, count;
int i=0;
srand(time(NULL));
while(i< words){
int r=rand()% words +1;
for (x = 0; x < i; x++)
{
if(array[x]==r){
break;
}
}
if(x==i){
array[i++]=r;
}
}
for(p=0;p<words;p++){
printf("%d ", array[p]);

Thread 1: EXC_BAD_ACCESS (code=1, address=0x68 [duplicate]

I am new to C programming and I am getting a THREAD 1: EXC_BAD_ACCESS(code = 1, address 0x68)
when I run my program. The purpose of my code is to read from a txt file that contains positive and negative numbers and do something with it.
#include <stdio.h>
int main (int argc, const char * argv[]) {
FILE *file = fopen("data.txt", "r");
int array[100];
int i = 0;
int num;
while( fscanf(file, "%d" , &num) == 1) { // I RECEIVE THE ERROR HERE
array[i] = num;
printf("%d", array[i]);
i++;
}
fclose(file);
for(int j = 0; j < sizeof(array); j++){
printf("%d", array[j]);
}
}
After
FILE *file = fopen("data.txt", "r");
Say
if(file == 0) {
perror("fopen");
exit(1);
}
Just a guess, the rest of the code looks ok, so likely this is the problem.
Also worth noting that you might have more than 100 numbers in your file, in which case you will blow past the size of your array. Try replacing the while loop with this code:
for (int i = 0; i < 100 && ( fscanf(file, "%d" , &num) == 1); ++i)
{
array[i] = num;
printf("%d", array[i]);
}
Do you have the file "data.txt" created and local?
touch data.txt
echo 111 222 333 444 555 > data.txt
Check that your file open succeeded.
Here is a working version,
#include <stdio.h>
#include <stdlib.h> //for exit
int main (int argc, const char * argv[])
{
FILE *fh; //reminder that you have a file handle, not a file name
if( ! (fh= fopen("data.txt", "r") ) )
{
printf("open %s failed\n", "data.txt"); exit(1);
}
int array[100];
int idx = 0; //never use 'i', too hard to find
int num;
while( fscanf(fh, "%d" , &num) == 1) { // I RECEIVE THE ERROR HERE
array[idx] = num;
printf("%d,", array[idx]);
idx++;
}
printf("\n");
fclose(fh);
//you only have idx numbers (0..idx-1)
int jdx;
for(jdx = 0; jdx<idx; jdx++)
{
printf("%d,", array[jdx]);
}
printf("\n");
}

Arranging a character array using bubble sort

Here is my code so far. I am perfectly able to sort files holding numbers but clueless when it comes to characters. It takes in a file of my choosing and outputs another file with the sorted array. But so far all I'm getting are blank files and I can't figure out why.
So how can I fix my code to sort an array of characters and then output it?
#include <stdio.h>
int bubble_sort(char *a, int n);
int main(void) {
char a[10];
int n = sizeof a / sizeof a[10];
int i;
char inname;
char outname;
printf("Enter input name: ");
scanf("%s", &inname);
printf("Enter output name: ");
scanf("%s", &outname);
FILE *in, *out;
out = fopen(&outname, "w");
if ((in = fopen(&inname, "r")) == NULL) {
printf("File not found\n");
}
else {
for (int i = 0; i < 10; i++)
{
fscanf(in, "%s ", &a[i]);
}
bubble_sort(a, n);
for (i = 0; i < 10; i++) {
printf("%s\n", a[i]);
fprintf(out, "%s\n", a[i]);
}
}
fclose(in);
fclose(out);
return 0;
}
int bubble_sort(char *a, int n) {
int i, j;
char temp;
for (j = 1; j<n; j++)
{
for (i = 0; i<n - j; i++)
{
if ((int)a[i] >= (int)a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
return a[i];
}
The basic problem, as I can see, is with
scanf("%s", &inname);
In your code, inname is a single char, which cannot hold string inputs. You'll be needing an array.
You need to change
char inname;
char outname;
to
#define NAMSIZ 32
char inname[NAMSIZ] = {0};
char outname[NAMSIZ] = {0};
and then,
scanf("%31s", inname);
and accordingly.
Same problem exist with fscanf(in, "%s ", &a[i]);, too.

Error when trying to read in numbers from txt file in C

I am new to C programming and I am getting a THREAD 1: EXC_BAD_ACCESS(code = 1, address 0x68)
when I run my program. The purpose of my code is to read from a txt file that contains positive and negative numbers and do something with it.
#include <stdio.h>
int main (int argc, const char * argv[]) {
FILE *file = fopen("data.txt", "r");
int array[100];
int i = 0;
int num;
while( fscanf(file, "%d" , &num) == 1) { // I RECEIVE THE ERROR HERE
array[i] = num;
printf("%d", array[i]);
i++;
}
fclose(file);
for(int j = 0; j < sizeof(array); j++){
printf("%d", array[j]);
}
}
After
FILE *file = fopen("data.txt", "r");
Say
if(file == 0) {
perror("fopen");
exit(1);
}
Just a guess, the rest of the code looks ok, so likely this is the problem.
Also worth noting that you might have more than 100 numbers in your file, in which case you will blow past the size of your array. Try replacing the while loop with this code:
for (int i = 0; i < 100 && ( fscanf(file, "%d" , &num) == 1); ++i)
{
array[i] = num;
printf("%d", array[i]);
}
Do you have the file "data.txt" created and local?
touch data.txt
echo 111 222 333 444 555 > data.txt
Check that your file open succeeded.
Here is a working version,
#include <stdio.h>
#include <stdlib.h> //for exit
int main (int argc, const char * argv[])
{
FILE *fh; //reminder that you have a file handle, not a file name
if( ! (fh= fopen("data.txt", "r") ) )
{
printf("open %s failed\n", "data.txt"); exit(1);
}
int array[100];
int idx = 0; //never use 'i', too hard to find
int num;
while( fscanf(fh, "%d" , &num) == 1) { // I RECEIVE THE ERROR HERE
array[idx] = num;
printf("%d,", array[idx]);
idx++;
}
printf("\n");
fclose(fh);
//you only have idx numbers (0..idx-1)
int jdx;
for(jdx = 0; jdx<idx; jdx++)
{
printf("%d,", array[jdx]);
}
printf("\n");
}

Resources