passing uninitialized character array to function. Crashing - c

The string lengths are not getting the correct lengths, so the rest of the program doesn't work. I am trying to read 62 chars per line then print a new line with another 62 chars.
Can anyone help me correctly pass the char arrays to the output function?
#include <stdio.h>
#include <string.h>
#define _CRT_SECURE_NO_DEPRECATE
void output(char *wbuf, char *lbuf, int lineLength);
void readFile(FILE *getty, char *wbuf, char *lbuf);
FILE *getty;
int main(void) {
char wbuf[1000] = {0}, lbuf[1000] = {0};
if (fopen_s(&getty,"getty.txt", "r") != 0 )
{
printf("Failed to open getty.txt for reading.");
} else {
readFile(getty, wbuf, lbuf);
}
fclose(getty);
return 0;
}
void readFile(FILE *getty, char *wbuf, char *lbuf)
{
static int lineLength = 62;
while (!feof(getty))
{
fscanf(getty, "%s", wbuf);
output(wbuf, lbuf, lineLength);
}
}
void output(char *wbuf, char *lbuf, int lineLength)
{
int wbufLength, lbufLength, i = 0;
wbufLength = strlen(wbuf);
lbufLength = strlen(lbuf);
//prints incorrect
printf("wbuflength %d lbuflength %d\n", wbufLength, lbufLength);
// lengths
if ( (wbufLength + lbufLength) <= lineLength)
{
strcat(lbuf,wbuf); //lbuf should be 0 but it starts at
} //274, wbuf not correct either
else
{
strcat(lbuf,"\n");
lineLength += 62;
strcat(lbuf, wbuf);
}
}

The problem is your loop condition:
while (!feof(getty)) { ... }
The EOF flag is not set until after an input operation fails.
In your case, the loop loops, then the fscanf operation fails because it's at the end of the file but you don't check for that inside the loop, and you then call output even though nothing was read from the file. Then the loop continues and then it notices that the file have reached EOF.

Related

How do you assign structs into an array?

I have currently made this much of the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define STRSIZE 21
struct PInven{
int count;
struct PItem{
char name[STRSIZE];
int amount;
}Pitem;
}Pinven;//this needs to be an output file
int ReadInProduce (){
//read in file and check to see if the file exist or not.
FILE * PinFile = fopen("produce.txt","r");
if (PinFile == NULL){
printf("ERROR: WRONG FILE");
}
else{
printf("I did it!!\n");
}
//assigning the value gotten into the struct variable(but need to maybe change this since it needs to be an output)
fscanf(PinFile,"%d",&Pinven.count);
printf("%d\n", Pinven.count);
int i;
for(i =0; i <Pinven.count; i++){
fscanf(PinFile,"%20s %d",Pinven.Pitem.name, &Pinven.Pitem.amount);
printf("%s %d\n",Pinven.Pitem.name, Pinven.Pitem.amount);
}
//making an array to hold the variables
//FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
return 0;
}
From there I want to get the file that is read to the structs to be printed out into an array so that later on I can make a function that will be able to compare to the to it.
Basically a store management system. Where the file of the inventory is read in and compared to the file that is store and return a new value for the amount of produce now either left or gained.
10 //number of items that will be stored in the store
apple 19
banana 31
broccoli 9
...
In general, it's a really bad idea to include header information in the file about the number of entries in the file. You want to be able to do stream processing, and that will be more difficult if you need that meta-data. More importantly, it is important to understand how to write the code so that you don't need it. It's not really that difficult, but for some reason people avoid it. One simple approach is just to grow the array for each entry. This is horribly inefficient, but for the sake of simplicity, here's an example that expects the file not not include that first line:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <limits.h>
#define STRSIZE 128
struct PItem{
char name[STRSIZE];
int amount;
};
struct PInven{
int count;
struct PItem *PItem;
};
static void
grow(struct PInven *p)
{
p->PItem = realloc(p->PItem, ++p->count * sizeof *p->PItem);
if( p->PItem == NULL ){
perror("out of memory");
exit(1);
}
}
int
ReadInProduce(struct PInven *P, const char *path)
{
FILE * PinFile = fopen(path, "r");
if( PinFile == NULL ){
perror(path);
exit(1);
}
char fmt[64];
int max_len;
max_len = snprintf(fmt, 0, "%d", INT_MAX);
snprintf(fmt, sizeof fmt, "%%%ds %%%dd", STRSIZE - 1, max_len - 1);
grow(P);
struct PItem *i = P->PItem;
while( fscanf(PinFile, fmt, i->name, &i->amount) == 2 ){
i += 1;
grow(P);
}
P->count -= 1;
fclose(PinFile); /* Should check for error here! */
return P->count;
}
int
main(int argc, char **argv)
{
struct PInven P = {0};
char *input = argc > 1 ? argv[1] : "produce.txt";
ReadInProduce(&P, input);
struct PItem *t = P.PItem;
for( int i = 0; i < P.count; i++, t++ ){
printf("%10d: %s\n", t->amount, t->name);
}
}
As an exercise for the reader, you should add some error handling. At the moment, this code simply stops reading the input file if there is bad input. Also, it would be a useful exercise to do fewer reallocations.
you should change Structure of PInven to it can save a dynamic array of Pitem with a Pitem pointer.
tested :
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define STRSIZE 21
typedef struct {
char name[STRSIZE];
int amount;
} Pitem;
struct PInven {
int count;
Pitem *pitem;
} Pinven; // this needs to be an output file
int main() {
// read in file and check to see if the file exist or not.
FILE *PinFile = fopen("produce.txt", "r");
if (PinFile == NULL) {
printf("ERROR: WRONG FILE");
} else {
printf("I did it!!\n");
}
// assigning the value gotten into the struct variable(but need to maybe
// change this since it needs to be an output)
fscanf(PinFile, "%d", &Pinven.count);
Pinven.pitem = (Pitem *)malloc(sizeof(Pitem) * Pinven.count);
printf("%d\n", Pinven.count);
int i;
for (i = 0; i < Pinven.count; i++) {
fscanf(PinFile, "%20s %d", Pinven.pitem[i].name,
&Pinven.pitem[i].amount);
// printf("%s %d\n",Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
for (i = 0; i < Pinven.count; i++) {
printf("%s %d\n", Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
// making an array to hold the variables
// FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
// remember free
free(Pinven.pitem);
return 0;
}

Trying to write a C function to read in stdin to elements of a struct

I have no idea how to call the function or what arguments to put in it. I've written the code in the main function, but I want to put it in a separate function I can call into main later. Would love some help on how I can do this!
The input comes from stdin
Here is the code (in the main function) that I want to put into a separate function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* * * Define Constants * * */
#define WORD_LEN 22
#define MAX_NUM_POS_TAGS 5
#define SIZE_POS_TAG 4
#define MAX_NUM_VAR_FORMS 4
#define VAR_FORM_LEN 25
#define MAX_DICT_WORDS 100
/* * * Typedefs * * */
typedef char word_line_one[WORD_LEN+1];
typedef char word_line_two[MAX_NUM_POS_TAGS+1];
typedef char word_line_three[SIZE_POS_TAG+VAR_FORM_LEN*SIZE_POS_TAG+1];
//getword function prototype
int getword(char W[], int limit);
//check_if_valid function prototype
int check_if_valid(char in_char);
//stage1 function
int stage1(char ln1[], char ln2[], char ln3[]);
//main function
//stage 1
int main (int argc, char *argv[])
{
//define the struct for one word
struct
{
word_line_one line_one;
word_line_two line_two;
word_line_three line_three;
}one_word_dict_t;
//reading line 1
char temp1[WORD_LEN+1];
getword(temp1, WORD_LEN+1);
strncpy(one_word_dict_t.line_one, temp1,WORD_LEN+1 );
//reading line 2
getword(one_word_dict_t.line_two,MAX_NUM_POS_TAGS+1);//do something about spaces in between tags!
//reading line 3
getword(one_word_dict_t.line_three,SIZE_POS_TAG+VAR_FORM_LEN*SIZE_POS_TAG+1);
//printing the word in the format:
printf("==========================Stage 1==========================\n");
printf("Word 0: %s\n", one_word_dict_t.line_one);
printf("POS: %s\n", one_word_dict_t.line_two);
printf("Form: %s\n", one_word_dict_t.line_three);
//stage 1 ends here
}
//getword function def
/* Extract a single word out of the standard input, of not
more than limit characters. Argument array W must be
limit+1 characters or bigger. */
int
getword(char W[], int limit)
{
int c, len=0;
/* first, skip over any non alphabetics */
while ((c=getchar())!=EOF && !check_if_valid(c))
{
/* do nothing more */
}
if (c==EOF)
{
return EOF;
}
/* ok, first character of next word has been found */
W[len++] = c;
while (len<limit && (c=getchar())!=EOF && check_if_valid(c))
{
/* another character to be stored */
W[len++] = c;
}
/* now close off the string */
W[len] = '\0';
return 0;
}
//check if valid function, used in modified version of getword():
int check_if_valid(char in_char)
{
if ((('A'<=in_char)&&(in_char<='Z')) || (('a'<=in_char)&&(in_char<='z')) ||
(('0'<=in_char)&&(in_char<='9')))
{
return 1;
}
else
{
return 0;
}
}

C function returning different values while calling from main function

I have written a program which read values from a the file. The data in the file is in following format.
100 Full Name SomeDetails.
234 Full Name SomeDetails
Following is the program which i wrote.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 10
struct student
{
int rollno;
char name[20];
char course[25];
};
int main()
{
FILE *fptr;
fptr=fopen("records.txt","r");
struct student s[10];
int i=0,tstudent=0;
char che;
char line[100];
//SECTION : 1.1 -> READING NUMBER OF LINES
while(!feof(fptr))
{
che=fgetc(fptr);
if(che=='\n')
{
tstudent++;
}
}
printf("Total Lines in File = %d\n",tstudent);
fclose(fptr);
//SECTION : 1.2 -> READING RECORDS FROM FILE
fptr=fopen("records.txt","r");
char newString[20][20];
int ii,j,ctr;
j=0;
ctr=0;
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(ii=0; ii<=(strlen(line)); ii++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[ii]=='\t'||line[ii]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[ii];
j++;
}
}
}
for(ii=0; ii < ctr; ii++)
{
printf("\n%s",newString[ii]);
}
printf("Value of ctr = %d",ctr);
fclose(fptr);
}
Above code is working fine, BUT all the code is in main function, but i want to make a separate function which can be called from main file and return me every data of file in two dimensional or one dimensional array as return value.
Any help/suggestions would be appreciated.
I tried following CODE as a separate function.. NOT WORKING.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char readfile(int tstudent,FILE* filename)
{
//FUNCTION TO READ RECORDS FROM FILE.
FILE *fptr;
int i,k;
char line[100];
char newString[20][20];
int j=0,ctr=0;
fptr=fopen("records.txt","r");
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(k=0; k<=(strlen(line)); k++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[k]=='\t'||line[k]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[k];
j++;
}
}
}
return newString;
}
I defined a new variable char results[] in main function.. and tried to called the function as follows
results[]=readfile(tstudent,fptr)
but when trying to read results.. its showing garbage
char readfile(int tstudent,FILE* filename)
...
char newString[20][20];
...
return newString;
That can't be a good thing, right? You define readFile to return one single character (not a pointer, just one byte) and then return an array instead. We should not be surprised the compiler complained.
If you "fix" that be redefining the return type, you still have a problem because newString is an automatic local variable. The storage (memory) it defines is undefined outside the function.
The easiest way for a function to populate a structure (or array) in C is for the caller to pass it as a function parameter. So you wind up with something more like:
int readfile( FILE* input, char newString[][20], int tstudent )
where newString is defined the same way as you have it, but by the caller, not in readfile. Cf. the stdio functions like fgets; most of them require the caller to define the buffer they read into.
I'll just point out a few more mistakes.
Whenever you call a function -- especially an I/O function -- check for errors. You may want to read tstudent records, but how many are there? If you ask for 5 and find only 1, what then? Your read loop must test for end-of-file, and readfile must return the number of records read, else the caller will never know. Compare with how fread(3) works. Those Unix guys knew a thing or two about how to define a function!
Now your function looks something like this:
int readfile( FILE* input, char newString[][20], int tstudent ) {
char line[100], *s;
int i=0;
for( ; i < tstudent && (s = fgets(line, sizeof(line), input)) != NULL; i++ ) {
/* do stuff with line */
}
/* check for EOF/error if s is NULL, and report */
return i;
}

returning 2d array in C…

I'm a total noob in C. I can't make the connect between this function and main. I'm trying to print out a 2d array and I keep getting segmentation fault. Any help would be greatly appreciated.
EDIT: When I changed the last line 'printf("%d:[%s]\n",i,*(p+i))' from %s to %c, I get the first word in the file i'm reading from. So turns out that something is in fact being returned from my function. Now just need to figure out how to get it to return words from other lines in the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define num_strings 20
#define size_strings 20
int *read_file(){
int j = 0;
static char text[num_strings][size_strings];
FILE *fp;
int x;
fp = fopen("dictionary2.txt", "r");
char s[100];
while(!feof(fp)) {
x = fscanf(fp,"%[^\n]",s);
fgetc(fp);
if (x==1) {
strcpy(text[j],s);
j++;
}
}
return text;
}
int main() {
int *p;
p = read_file();
int i;
for(i = 0; i < 10; i++) {
printf("%d:[%s]\n",i,*(p+i));
}
return(0);
}
In general, you should be creating your array in main() and passing it in, this kind of behavior is very unorthodox. However, if you do insist on doing it this way, you have to return a pointer to your array, since you cannot return arrays in C.
This is the kind of thing you'll need:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define num_strings 20
#define size_strings 20
typedef char (*PARR)[num_strings][size_strings];
PARR read_file(int * wordsread)
{
static char text[num_strings][size_strings];
FILE *fp;
if ( (fp = fopen("dictionary2.txt", "r")) == NULL ) {
fprintf(stderr, "Couldn't open file for reading\n");
exit(EXIT_FAILURE);
}
char s[100];
int j = 0;
while ( j < num_strings && fgets(s, sizeof s, fp) ) {
const size_t sl = strlen(s);
if ( s[sl - 1] == '\n' ) {
s[sl - 1] = 0;
}
if ( (strlen(s) + 1) > size_strings ) {
fprintf(stderr, "String [%s] too long!\n", s);
exit(EXIT_FAILURE);
}
strcpy(text[j++], s);
}
fclose(fp);
*wordsread = j;
return &text;
}
int main(void)
{
int wordsread = 0;
PARR p = read_file(&wordsread);
for ( int i = 0; i < wordsread; ++i ) {
printf("%d:[%s]\n", i, (*p)[i]);
}
return 0;
}
which, with a suitable input file, outputs:
paul#horus:~/src/sandbox$ ./twoarr
0:[these]
1:[are]
2:[some]
3:[words]
4:[and]
5:[here]
6:[are]
7:[some]
8:[more]
9:[the]
10:[total]
11:[number]
12:[of]
13:[words]
14:[in]
15:[this]
16:[file]
17:[is]
18:[twenty]
19:[s'right]
paul#horus:~/src/sandbox$
Note this only works because you declared your array in read_file() as static - don't return pointers to local variables with automatic storage duration in this way.
Try moving your #defines back and changing your function header to return a pointer to arrays of size_strings characters, as follows:
#define num_strings 20
#define size_strings 20
char (*read_file())[size_strings] {
Or alternately, with a typedef:
#define num_strings 20
#define size_strings 20
typedef char (*PCharArr)[size_strings];
PCharArr read_file() {
...and change the type of p in main accordingly:
char (*p)[size_strings];
That will return (a pointer to the first element of) an array of character arrays, which is more or less equivalent to a 2D array of char.
Update, oh I see, you pasted the code from main to the function, I know what happened here, you assumed p[20][20] is the same as a p* or maybe a p**, that's not correct, since now if you do *(p+1), the compiler doesn't know each element in p is 20 wide instead of 1 wide. You approach here should be to declare a pointer to an array of strings in read_file and return that instead:
static char text[num_strings][size_strings];
static char *texts[num_strings]
...
while....
....
if (x==1)
{strcpy(text[j],s);texts[j]=text[j];j++;}
return texts;
your p should be char* not int*. You also need to terminate the loop if 20 items have been read in.

How does this retarget.c work

Can someone explain to me how this retarget.c works?
I am trying to send integers to and from the uart of a microcontroller, i have been successful with using fgets to get a char (16 bits) and returning an integer using the atoi function in the Uart Interupt service routine but I am trying to get an integer using scanf, i am thinking i need to change the retarget file outlined below?
#include <stdio.h>
#include <time.h>
#include <rt_misc.h>
#define AHB_LED_BASE 0x50000000
#define AHB_UART_BASE 0x51000000
#pragma import(__use_no_semihosting)
struct __FILE {
unsigned char * ptr;
};
FILE __stdout = {(unsigned char *) AHB_UART_BASE};
FILE __stdin = {(unsigned char *) AHB_UART_BASE};
int fputc(int ch, FILE *f)
{
return(uart_out(ch));
}
int fgetc(FILE *f)
{
return(uart_in());
}
int ferror(FILE *f)
{
return 0;
}
int uart_out(int ch)
{
int* UARTPtr;
UARTPtr = (int*)AHB_UART_BASE;
*UARTPtr = (int)ch;
return(ch);
}
int uart_in()
{
int ch;
int* UARTPtr;
UARTPtr = (int*)AHB_UART_BASE;
ch = *UARTPtr;
uart_out(ch);
return((int)ch);
}
void _ttywrch(int ch)
{
fputc(ch,&__stdout);
}
void _sys_exit(void) {
while(1);
}
//------------------------------------------------------------------------------
// Cortex-M0
//------------------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
#include <rt_misc.h>
#include <stdlib.h>
#define AHB_LED_BASE 0x50000000
#define AHB_UART_BASE 0x51000000
void UART_ISR(void)
{
int sample;
printf("the value entered is %d\n", sample);
}
//////////////////////////////////////////////////////////////////
// Main Function
//////////////////////////////////////////////////////////////////
int main() {
{
int sample;
scanf ("%d",&sample);
}
}
The scanf function will need ungetc because it must scan ahead in the buffer to see when fields end. E.g., when looking for a number, it needs to pull one character after the number to see where the number ends. When it sees the non-number character, it needs to put it back into the stream so the next call to getc will get it.
Something like this:
struct __FILE
{
unsigned char * ptr;
int unchar; /* place to keep the character put back in the stream */
};
FILE __stdout = {(unsigned char *) AHB_UART_BASE, -1};
FILE __stdin = {(unsigned char *) AHB_UART_BASE, -1};
int fgetc(FILE *f)
{
int c;
if (f->unchar == -1)
{
c = uart_in(); /* just read a character */
}
else
{
c = f->unchar; /* reuse the character put back by ungetc */
f->unchar = -1; /* mark it as used */
}
return c;
}
int fungetc(int c, FILE *f)
{
unsigned char uc = c; /* POSIX says that it is converted first to unsigned char */
f->unchar = (int )uc; /* put back the character */
return (int )uc;
}

Resources