C File input & output - c

I made a simple dictionary code, and surfed for an hour, and I found a file I/O code. But my compiler(I use Microsoft visual C++) says my code(unfortunately, the core part of the code) is wrong. but I can't get it. What is actually wrong and why???
/*
DosDic ver 1.0.0 2015-07-03
*/
#include<stdio.h>
#include<string.h>
char key = 0;
FILE *fp; //set a file pointer var
fp = fopen("dicdata.dat","r"); //open a file
int b = 0;
int trial = 0;
char result[];
char searchfor[] = fp; //save a whole list of dictionary in a var
int i;
char sb[]; //var for search in a list
int getsearchtrial(char sb[]){
for(i=0;i=strlen(sb);i++){ //how much I tried to reach to the word
switch((int)searchfor[b]-(int)sb[i]){ //are two alphabets same?
case 0 :
default : i=0;
}
b++; //keep finding in a list
trial++; //try again
}
return trial;
}
int adress;
int mainpage(){
printf("Type what you want to search : ");
scanf("%c",sb[ ]);
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress; //where the word is located in the list
for(i = adress;i = adress + 30; i++){ //print
printf("%c",searchfor[i]);
}
printf("Thank you for using DosDic ver.1.0!"); //thank you!
}
void main(){ //call all those functions
mainpage();
fclose(fp); //close list
}
//and whats wrong with this? i cant even get it, but it's not working

Multiple issues.
First of all, you can't assign the result of fopen to fp outside the body of a function; you must move fp = fopen("dicdata.dat", "r"); to within the body of one of your functions (getsearchtrial most likely).
Secondly, you don't read from a file by simply assigning a file pointer to an object; you must use a library function like fscanf or fread or fgets. Assuming your file contains a single string of length 80, you'd need to write something like
char searchfor[81] = {0}; // make sure string is initially empty,
// extra space for string terminator
if ( !fgets( searchfor, sizeof searchfor, fp) )
{
// error reading from file
}
Of course, this depends on how your input file is structured. If it contains a list of strings, then you'll need to use a multidimensional array (or some other structure).
Third, when you declare an array, must specify its size before you can use it. result and searchfor are incomplete array definitions.
Finally, this line
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress;
needs to be reversed; the target of an assignment must be on the left of the assignment operator.
You need to step back and learn how to write C code from the ground up.

There is so much wrong I'm not even going to itemise it all here - most of it seems to stem from your lack of understanding of arrays in C.
Most notably...
You can't declare an array and not initialise it or specify a size.
You can't assign a FILE * to a char array (and expect decent
results).
You can't execute a statement like fp = fopen at the
global scope like you are.
Try this tutorial and you may fix 95% of your problems, then go from there.

Related

How to fwrite() two different kinds of variables within a struct?

I'd like to add an array of type 'struct classes' (definition included below) to a file. For instance, if allClasses[0].title is equal to "Math" and allClasses[0].class_id is equal to 1, I'd like the file to have the following input:
1Math/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0
If another class is added with a title of Science, then the file should now read
1Math/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/02Science/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0
What appears to happen is that, although the code will catch the char array part of the struct (math / science in the example), it will have trouble with the int and instead print out junk in its place (and the junk is often times longer than 1 character / 1 int long).
From experience, the code format (with a few adjustments, of course) works just fine when using a struct with variables that are only char arrays. However, it glitches out when using ints. Is this because of ASCII conversions, or something similar? How can I adjust the code so that I get the input with both the int and the char array?
void addClasses(char *given_title) {
FILE *fp;
fp = fopen("classes.db", "r");
if (numClasses == 0 && fp != NULL) {
findClasses();
}
strcpy(allClasses[numClasses].title, given_title);
allClasses[numClasses].class_id = numClasses + 1;
numClasses++;
fclose(fp);
fp = fopen("classes.db", "w");
for (int i = 0; i < numClasses; i++) {
struct classes *object = malloc(sizeof(struct classes) - 1);
memset(object, 0, sizeof( struct classes ));
object->class_id = allClasses[i].class_id;
strcpy(object->title, allClasses[i].title);
fseek(fp, numClasses * (sizeof(struct classes) - 1), SEEK_END);
fwrite(object, sizeof(struct classes) - 1, 1, fp);
}
fclose( fp );
}
The struct:
struct classes {
int class_id;
char title[30];
};
A bit of extra (possibly unnecessary) background on some of the components in the code: the bit at the beginning of the method tries to read the file and start to fill the array with any structs that were already put into the file before starting the program. I'm not including the code for that, since the aforementioned glitch happens even when I have a fresh classes.db file (and thus, even when findClasses() never runs).
Small note, by the way: I can't change the class_id into a char / char array. It needs to be an int.
If you want to add it in the text form:
fprintf(fp, "%d,\"%s\"\n", object -> class_id, object -> title);
when you open the file with "w" you create new empty file. When you write to the file you do need to fseek.
If you want to append to existing file use "a" or "a+" instead.

Array of strings reading its input from file.txt C programming

I am having a problem and cant tell what is it.
struct arrayDB {
char *user[MAX_SIZE];
char *pass[MAX_SIZE];
char db[10][2];
};
void readFile(char fileName[100])
{
char* word ;
char line[90];
FILE *passFile;
int rowC=0;
int chk=0;
passFile=fopen(fileName,"rt");
while(fgets(line,90,passFile)!=NULL)
{
word=strtok(line," ");
rowC=rowC+1;
while(word!=NULL)
{
printf("Count=%i \n",rowC);
if(chk==0)
{
printf("word:%s\n",word);
DB.user[rowC]=word;
chk=1;
}
else
{
printf("word:%s\n",word);
DB.pass[rowC]=word;
}
printf("r=%s , c=%s\n",DB.user[rowC],DB.pass[rowC]);
word=strtok(NULL," ");
}
chk=0;
}
int i;
for(i=1; i<6;i++)
{
printf("- %s , %s \n",DB.user[i],DB.pass[i]);
}
}
but the output I am getting that all the array elements is the same value which is the last word in the file
as you can see in the pic
thanks
You're reading every line into the same string line. Then when you use strtok(), it's returning pointers into this string, and you're storing these pointers into DB. So all the records in DB are pointing to locations in line, which gets overwritten each time you read another line from the file. When everything is done, line contains the contents of the last line of the file, and all the DB entries point to that.
Another problem is that line is a local variable, and pointers to it become invalid when the function returns.
To solve both problems, you need to make copies of the string and store these in DB. For example:
DB.user[rowC]= strdup(word);
This also means that when you're done with a DB record, you need to call free(DB.user[i])
Some suggestions:
First, learn to use a debugger. There are free ones, get one and turn it on to find all of these errors (that is what I did here)
Next, for the code example you show to compile, the struct definition needs to support your code (currently, DB is not defined)
typedef struct
{
char *user[MAX_SIZE];
char *pass[MAX_SIZE];
char db[10][2];
}arrayDB;
arrayDB DB;//define DB
Next,
you need to allocate space for your string arrays:
something like:
for(i=0;i<MAX_SIZE;i++ )
{
DB.user[i] = malloc(100);
DB.pass[i] = malloc(100);
}
Next, don't forget to free them when done using them.
for(i=0;i<MAX_SIZE;i++ )
{
free(DB.user[i]);
free(DB.pass[i]);
}
Next, you cannot assign a string using an equal operator:
DB.pass[rowC]=word;
use strcpy (or some other string function) instead:
strcpy(DB.pass[rowC],word);
Next, this line:
printf("r=%s , c=%s\n",DB.user[rowC],DB.pass[rowC]);
Is called after a conditional statement where either DB.user[rowC] or DB.pass[rowC] will be written to, never both. Suggest splitting this printf statement to print one or the other, and place it into the appropriate conditional branch.

Reading from csv file and separating into variables in C

I've been looking for answer here, but didn't find solution for this particular problem.
I have this csv file
For imagination, I should have creating hockey players from this .csv file as
enum POZICE { UTOCNIK = 'U', OBRANCE = 'O', BRANKAR = 'B' };
typedef struct hrac {
int cislo;
char jmeno[50];
enum POZICE pozice;
int utocnaSila;
int obrannaSila;
struct hrac *dalsi;
} tHrac;
Number, name, position of player(keeper, defender, etc.), his attack power, defensive power and link to next player.
Creating method:
tHrac* vytvorHrace(int cislo, char* jmeno, enum Pozice pozice, int utocnaSila, int obrannaSila) {
tHrac* hrac = (tHrac*)malloc(sizeof(tHrac));
hrac->cislo = cislo;
strcpy(hrac->jmeno, jmeno);
hrac->pozice = pozice;
hrac->utocnaSila = utocnaSila;
hrac->obrannaSila = obrannaSila;
hrac->dalsi = NULL;
}
And now the core of my problem, loading method
void nactiSeznamHracu() {
char *tmp1[30];
char *tmp2[30];
char *tmp3[30];
char *tmp4[30];
char *ch[255];
int a = 0;
FILE* soubor = fopen(SEZNAM, "r");
fgets(ch, sizeof(ch), soubor);
fputs(ch, stdout);
sscanf(ch, "% [^;]%[^;]", tmp1, tmp2); // parsing whole char *ch into smaller pieces, wont work
puts(tmp1,tmp2);
fscanf(soubor, "%c [^;]%s [^;]", tmp3,tmp4); // without saving first line into ch, and cutting it right away
puts(tmp3);
//token = strtok(ch, "\n");
//puts(token);
}
I can succesfully load first line, but when I try somehow cut the lines into smaller pieces, like Number,Name,Attack,Deffence,Position, it won't work(or cutting only header into smaller pieces), I tried many ways, more than I've here, but result was always the same... (first two lines of img is unrelated, was just testing tHrac, creating and writing)
My intention is to create for cycle where it will load first line, load it seperately into variable which i will use to create tHrac and then it skip into next line and same thing ...
But my experience with C is low, so that's why I'm turning on you. Anyone can help?
sscanf(ch, "% [^;]%[^;]", tmp1, tmp2); // parsing whole char *ch into
puts(tmp1,tmp2);
fscanf(soubor, "%c [^;]%s [^;]", tmp3,tmp4);
tmp1 ,tmp2 and all are array 30 of pointers to char , and passing wrong arguments would cause undefined behavior.
In case either you need to use individual pointer of these arrays after allocating memory to them ,
Or use them as array to char or char * , and you need to allocate memory in latter case and then pass them to sscanf or fscanf.
Note- Also you should check return value of sscanf and fscanf functions .

C - fprintf() & printf() deleting array element memory

I fairly new to C Programming, but fprintf() & printf() is behaving strangely and I'm so confused on why--I need some help understanding and diagnosing this issue.
fprintf() Deleting Element of Array
First off, I'm passing in a populated malloc allocated four element char** array into a simple function that will write to a file, everything in the array appears normal and all four elements contain the correct data. The function call in main() looks like this. My array in question is header.
Note: I had to cast this normal (char** array) as a constant in this function parameter, due to the function header parameter. Our professor gave us the header file and we cannot change anything in them.
pgmWrite((const char**) header, (const int**) matrix,
rowPixels, colPixels, outFile);
Next, stopping debugger just before it executes the fprintf() & printf() functions, screenshot showing the array is still populated with my 4 elements.
pgmWrite() - Showing array is still fine
Observe the 4th element of the array after execution of fprintf().
After fprintf() executes, element 3 memory is wiped out.
When run, printf() executes the printing of the array exactly what is shown in the debugger, ending at the 3rd element. Often printing nothing in that spot or in rare cases garbage characters. The behavior of printf() is exactly the same as how fprintf() is working as well.
I'm at a loss here guys, please help me understand what I'm doing wrong. I can only provide these two screenshots, based on me being a new member. I'll try to provide as much information as possible. Thank you. Here is a simplified version of my program. Keep in mind, the professor gave us the function declarations and told us we cannot change them. So, I have to work with what I have here. Also, since this is fileIO, you need to find a *.pgm file to test this.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define rowsInHeader 4
#define maxSizeHeadRow 200
int ** pgmRead( char **header, int *numRows, int *numCols, FILE *in ){
// INITIALIZING
char *headArr[rowsInHeader][maxSizeHeadRow];
char buffer[100];
int r = 0;
fpos_t pos;
// CREATE: Header
while (r < 4){
// IF: Row in pgm file header lists the dimensions of matrix
if (r == 2){
// CURSOR: Saving pointer location in file (see notes in header for method reference)
fgetpos(in, &pos);
// ASSIGN: Dereference column and row pointers from file
fscanf(in, "%d %d", numCols, numRows);
// CURSOR: Moving back to saved pointer location (see notes in header for method reference)
fsetpos(in, &pos);
}
// ASSIGN: Copying header row into array
fgets(buffer, maxSizeHeadRow, in);
strcpy((char*)headArr[r], buffer);
// POINTER: Reference pointer to headArr[]
header[r] = (char*)headArr[r];
// TRAVERSE: To next row in file
r++;
}
// NOTE: Placeholder for return type
return 0;
}
int pgmWrite( const char **header, const int **pixels, int numRows, int numCols, FILE *out ){
// INITIALIZING
int i = 0;
// WRITE: Header
for (i = 0; i < rowsInHeader; i++){
fprintf(out, "%s", header[i]);
printf("%s", header[i]);
}
return 0;
}
int main(int argc, char *argv[]){
char **header = (char**)malloc(rowsInHeader * sizeof(char));
FILE *inFile = fopen("smallFile.pgm", "r");
FILE *outFile = fopen("TestPicture.ascii.pgm", "w");;
int rowPixels = 0;
int colPixels = 0;
int **matrix = NULL;
// READ & WRITE
matrix = pgmRead(header, &rowPixels, &colPixels, inFile);
pgmWrite((const char**)header, (const int**)matrix, rowPixels, colPixels, outFile);
// FINALIZING
fclose(inFile);
free(header);
return 0;
}
You are not allocating your array correctly. This line:
char **header = (char**)malloc(rowsInHeader * sizeof(char));
makes header point to an uninitialized region of memory , size 4 bytes.
Then inside your PGM function you write:
header[r] = (char*)headArr[r];
The code header[r] means to access the r'th pointer stored in the space pointed to by headArr. But since that space is only 4 bytes big, you're actually writing off into the wild blue yonder.
Also, (char *)headArr[r] is a mistake. If you did not use the cast, your compiler would have warned you about this mistake. You should avoid using casts in your code, especially using them to make warnings go away. You're saying to the compiler "Ssh, I know what I'm doing" when in fact you don't know what you are doing.
The entire approach with headArr is flawed from the start: even if you had actually written the right code to implement what you were trying, you'd be returning pointers into space which is deallocated when the function returns.
Basically the whole pgmRead function is a complete mess and it'd be easier to start from scratch. But this time, think carefully about when and where you are allocating memory, and what the types are of your expressions, and don't use casts. Let the pgmRead function do all the allocation.
(Unfortunately, based on your description it looks like you will have to use your casts to call the pgmWrite function since that has a mistake in its signature. const int ** should be const int * const *, and similarly for const char **. I'd recommend to actually change pgmWrite's signature accordingly, get your program working, and then once everything is good, then go back to the broken version that you are forced to use.)
Reading C FAQ - arrays and pointers might be useful too.

C - Convert string to variable name

How can I convert a string into a variable name? E.g. I have a list of strings:
"str1", "str2", "str3", etc.
And a structure:
struct my_struct {
int str1;
int str2;
int str3;
} m = {5, 10, 15, ... etc};
Given a string "str2", I want to print the variable associated with that
name m.str2. Does C have any way to do this?
Thank you!
This is simply not possible in C.
Check out this question for more details.
How to return a variable name and assign the value of the variable returned in c
To quote Wichert, 'I suggest that you reconsider the problem you are trying to solve and check if there might not be a better method to approach it. Perhaps using an array, map or hash table might be an alternative approach that works for you.'
In C you cannot create variable or symbol names dynamically.
Here's one way.
if ( strcmp(str, "str2") == 0 )
{
// Use m.str2
}
That will be a problem with hundreds of variables. You'll have to come up with some other mechanism in that case.
I will suggest a slightly simpler, albeit maybe not as efficient solution.
This was a solution I came up with for a project after consulting with one of my professors.
Essentially, strings are just ASCII characters, and C file containing variable names can be thought of in the same way.
Thus, suppose you have a list of strings that you would like to turn into variable names for integers.
First, define your structure in a header file that can be accessed by all files in your directory, for instance 'struct.h'.
The first step is to convert the string names to their respective integers
Simply create an empty header, called variable_names.h, include struct.h, and once and for all invoke the following loop in your main file:
const char *strings[] = {"str1", "str2", ... }
fp = fopen("variable_names.h", "a");
fprintf(fp, "#ifndef FILE1_H \n");
fprintf(fp, "#define FILE1_H \n");
fprintf(fp, "extern int* m_integers = {");
int i;
for(i = 0; i < sizeof(strings) - 1; i++){ fprintf(fp, "m.%s,", strings[i]);}
fprintf(fp, "m.%s } ", strings[i+1])
fprintf(fp, "#endif");
Now you have a linear mapping between the string name and value in your structure via the m_integers array. Next is to create some mapping that takes in the string name and points it to this integer. I will use UTHASH, but there are certainly other ways.
Thus, in your main file,
#include "uthash.h"
#include "variable_names.h"
...
struct opcode_table{
char* opcode_key;
int opcodes_val;
UT_hash_handle hh;
};
struct opcode_table *mapping = NULL;
struct opcode_table* s = NULL;
for (int i = 0; i < opcode_size; i++){
s = (struct opcode_table*) malloc(sizeof(*s));
s->opcodes_key = strings[i]; // the string
s->opcode_val = m_integers[i]; // the integer
HASH_ADD(hh,mapping, opcodes_key, sizeof(int),s);
}
^ Please go easy on the code, just a rough example of what could be done. I'm sure there are some mistakes, but high level I believe this should work.
As on overview, the idea is essentially, you wrote to an external file the ascii characters "m.string1", which once is written, is interpreted as an integer via the structure definition, yielding you your desired outcome. Now, you must simply look up the string in the hash table, and you get the integer in the structure.
Also, I would appreciate any feedback if someone finds a better way or this approach is flawed. Thanks!
Here is one way, please check the sample code I have written. I have used integer pointer ptr to do this.
#include <stdio.h>
#include <string.h>
const char *s[] = {"str1", "str2", "str3", "str4", "str5", "str6", "str7", "str8", "str9", "str10"};
struct temp
{
int str1;
int str2;
int str3;
int str4;
int str5;
int str6;
int str7;
int str8;
int str9;
int str10;
}m = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
main()
{
char str[10];
int *ptr;
int i;
ptr = &m.str1;
printf("enter string: \t");
scanf("%s", str);
for(i=0;i<10;i++)
{
if(strcmp(str,s[i]) == 0)
{
break;
}
}
printf("value = %d\n", *(ptr+i));
}
Please correct me if any mistakes.
What you are wanting is what the Smalltalk Language had used in it's Interpreter in the 1980;s and what Python still uses to create Object Variables from string char's through a TTY Command Shell Program in C language.
We do these by using structs with a nested struct next. But the actual variable, names are never actually declared. They are however matched by a conditional search for their stored char name in a struct or if it does not exist it creates them.
If it does exist in the struct list it will conditionally find() it and its stored value or assign its value depending on what your program has it designed to do.
An example of this is understood best by the Token's being used for (tok),(s),(t),(e) and several others as look-aheads read in by a token stream:
if (tok == "IDENT";) {
When it finds a identifier(variable tag from lex) token as above it will look ahead and fetch the variable name, then either create it, perform a calculation of its look-ahead contains another variable after another char type definition such as "CHAR" or "FLOAT"(for a double)etc.
What it does now is to set everything conditionally as it's being read into the struct list assigned by the tok token stream.
"CHAR" "x" "EQUALS" "INT" "5" "NEWL(for \N)" "CHAR" "y" "EQUALS" "INT" "5" "NEWL" "PRNT" "CHAR" "x" "NEWL".
So basically all variables through void functions are conditionally being assigned to a struct list and likewise having their values stored by them.
And it is not the variable you need to match its stored variable name. Its only the match it requires from a single tok variable and it's look-aheads that you need--
struct Var v; //--declared in .h then--
if(tok == 'CHAR') //--and--
v = {tok2, s, t} //
"tok2" being your vars char name and "s" and "t" being look-aheads to fetch, calculate and or assign them. Basically Python uses one C variable named tok to name them all. Then matches make them both dynamic and easy for Python to use them. atoi and strtod make integer and doublke conversion on the fly also. Its advanced stuff.
This whole process is called "Scanners" and "Calculators" in early ANCI C. Study Dennis Ritchie and Tobias Shrighner. Tobias worked on several Interpreters in fact.

Resources