Related
I have, I'm trying to read a binary file until end and print the result, I'm using and while with "feof" to read until end of file and printing each result, but I have a problem it is giving me double end result.
I'm still learning C, so I don't know why its giving me double end result, I have tried so many ways, but this was for me the best way and easiest that at least works, but now I'm stuck after 2 hours trying to fix it.
Result:
0
1
2
3
4
5
6
7
8
9
9
Expected:
0
1
2
3
4
5
6
7
8
9
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// https://www.aprendeaprogramar.com/cursos/verApartado.php?id=16007
struct Datos
{
int cero;
int uno;
int dos;
int tres;
int cuatro;
int cinco;
int seis;
int siete;
int ocho;
int nueve;
};
struct Datos datosEscrito = {0,1,2,3,4,5,6,7,8,9};
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
fwrite(&datosEscrito, sizeof(datosEscrito), 1, fichero);
fclose(fichero);
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
printf("%u", datoLeido);
printf("\n");
}
fclose(fichero2);
}
PD: I don't want the code fix, I want to understand why is giving me double end and an approach to fix the error myself, or another way to do the same. Thanks for the help.
Code edit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
int count=0;
while (count != 10)
{
fwrite(&count, sizeof(count), 1, fichero);
count++;
}
fclose(fichero);
// PARTE LEER
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
printf("%u", datoLeido);
printf("\n");
}
fclose(fichero2);
return 0;
}
The main problems in your program are that feof will only return a nonzero value when the previous fread (or other read operation) has detected an end-of-file condition and that you use the value even when fread would have told you by its return value that it has not read any data.
The functions feof and ferror are intended to distinguish between EOF and error after a failed file operation.
To fix the read loop you can use e.g.
do
{
/* we expect to read 1 member */
if(fread(&datoLeido, sizeof(datoLeido), 1, fichero2) == 1)
{
printf("%u", datoLeido);
printf("\n");
}
} while ((!feof(fichero2)) && !ferror(fichero2));
There are more problems in your code.
The format %u corresponds to a type unsigned int. For int you should use %d.
You write the binary representation of a structure struct Datos to a file, then you read back individual values of type int.
Although this seems to produce the expected result in your case it may not work in other cases. A structure can contain padding bytes that are not part of any structure field. These would have undefined values. In any case writing/reading the binary representation of variables is implementation-dependent. The data format may change when you use a different compiler (new version, different OS, different CPU...) or even with different compiler settings.
I was able to "fix" the problem, but i think it is a dirty fix, but at least works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
int count=0;
while (count != 10)
{
fwrite(&count, sizeof(count), 1, fichero);
count++;
}
fclose(fichero);
// PARTE LEER
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
if(!feof(fichero2))
{
printf("%d", datoLeido);
printf("\n");
}
}
fclose(fichero2);
return 0;
}
Thanks to all for the help and #David Schwartz gave me the hint after reading that i am not checking if the file end it before print the data
I'm having trouble loading from a file into a linked list, been trying the whole day
first of all this is my struct
typedef struct Sensor {
int id;
int intervalo;
char local[30];
char tipo[30];
//bool active;
int active;
struct Sensor* anterior;
struct Sensor* proximo;
} Sensor;
this is my save function which i think its working fine, since the file gets created and the content is there.
void gravaLista(Sensor* l) {
FILE *ficheiro;
Sensor* temp = l;
ficheiro = fopen("sensores.txt", "r+t");
if (ficheiro == NULL) {
ficheiro = fopen("sensores.txt", "w+t");
}
while (temp != NULL) {
fprintf(ficheiro, "%d%d%d%30s%30s", temp->id, temp->intervalo, temp->active,
temp->local, temp->tipo);
temp = temp->proximo;
}
fclose(ficheiro);
}
now where i cant seem to make this work regardless of what i read about it is the load function.
heres what i have atm
int CarregaTodos(Sensor** l) {
Sensor sens;
FILE *ficheiro;
int i = 0;
ficheiro = fopen("sensores.txt", "r+t");
if (ficheiro == NULL) {
printf("no file\n", "sensores.txt");
return i;
}
rewind(ficheiro);
while (fscanf(ficheiro, "%d%d%d%30s%30s", &sens.id, &sens.intervalo, &sens.active,
&sens.local, &sens.tipo) == 5) {
//novo() function returns a pointer to a new element and insereSensor adds the new element to the last position of the list
insereSensorFim(&l, novo(sens.id, sens.intervalo, sens.local, sens.tipo)); //this function inserts the new element at the end of the list
}
fclose(ficheiro);
return i;
}
the helper functions work fine outside of the load function, but when i try to print the list after loading nothing gets printed. what am i missing?
edit: ill just post the helper functions too
Sensor* novo(int id, int tempo, char* l, char* t) {
Sensor* novoSensor = (Sensor*)malloc(sizeof(struct Sensor));
//novoSensor->id = ++(*totalSens);
novoSensor->id = id;
novoSensor->intervalo = tempo;
strcpy(novoSensor->local, l);
strcpy(novoSensor->tipo, t);
novoSensor->active = 1;
novoSensor->anterior = NULL;
novoSensor->proximo = NULL;
//gravaSensor(novoSensor, (*totalSens), 1);
return novoSensor;
}
void insereSensorFim(Sensor** Lista, Sensor* novo) {
Sensor* atual = *Lista;
if ((*Lista == NULL))
(*Lista = novo);
else {
while (atual->proximo != NULL) {
atual = atual->proximo;
}
atual->proximo = novo;
novo->anterior = atual;
}
}
edit2: its fixed now, thanks to everyone who commented, you can read all the comments or just https://stackoverflow.com/a/44078897/8038340
Using printf() and scanf() properly is surprisingly hard. It's possible to do all sorts of magic with them, but you need to know how they work to be able to perform that magic.
In the example code, you make life more difficult for yourself by not including a record delimiter in the output. A newline is the conventional and simplest delimiter, but you can choose others if you wish, or no delimiter. However, if you choose no delimiter, you have to know information about the data that is not given in the question. If the strings never contain spaces, you can be less stringent in your formatting. But you must have some way of knowing where one number ends and the next one starts — you can't simply smush all the numbers together as the sample printf() format does unless they're all negative, or you add a plus sign to the positive number (%+d). There has to be some way to tell scanf() when to stop reading one and start on the next number.
This code is an elaboration of what I wrote in numerous comments. The output format uses fixed width fields; this makes it easier to read them. It does not assume there are no spaces in the strings, so it uses %29c to read 29 characters, and adds a null-terminator and removes trailing blanks via strip_blanks(). It includes code to print lists; it uses that code.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Sensor
{
int id;
int intervalo;
char local[30];
char tipo[30];
int active;
struct Sensor *anterior;
struct Sensor *proximo;
} Sensor;
static void insereSensorFim(Sensor **Lista, Sensor *novo);
static Sensor *novoSensor(int id, int tempo, char *l, char *t);
static const char *outfile = "sensores.txt";
static
void gravaLista(Sensor *l)
{
FILE *ficheiro = fopen(outfile, "w");
if (ficheiro == NULL)
{
fprintf(stderr, "Failed to open file '%s' for writing\n", outfile);
exit(1);
}
Sensor *temp = l;
while (temp != NULL)
{
fprintf(ficheiro, "%11d%11d%11d%-29.29s%-29.29s", temp->id, temp->intervalo, temp->active,
temp->local, temp->tipo);
temp = temp->proximo;
}
fclose(ficheiro);
}
/* Strip trailing blanks and null terminate string */
static inline void strip_blanks(char *data, size_t size)
{
assert(size > 0);
size_t offset = size - 1;
data[offset--] = '\0';
while (offset > 0 && data[offset] == ' ')
data[offset--] = '\0';
}
static
int CarregaTodos(Sensor **l)
{
Sensor sens;
FILE *ficheiro;
int i = 0;
ficheiro = fopen(outfile, "rt");
if (ficheiro == NULL)
{
fprintf(stderr, "Failed to open file '%s'\n", outfile);
exit(1);
}
while (fscanf(ficheiro, "%11d%11d%11d%29c%29c", &sens.id, &sens.intervalo, &sens.active,
sens.local, sens.tipo) == 5)
{
strip_blanks(sens.local, sizeof(sens.local));
strip_blanks(sens.tipo, sizeof(sens.tipo));
insereSensorFim(l, novoSensor(sens.id, sens.intervalo, sens.local, sens.tipo));
}
fclose(ficheiro);
return i;
}
static inline void str_copy(char *dst, const char *src, size_t size)
{
assert(size > 0);
strncpy(dst, src, size - 1);
dst[size - 1] = '\0';
}
static
Sensor *novoSensor(int id, int tempo, char *l, char *t)
{
Sensor *novoSensor = (Sensor *)malloc(sizeof(struct Sensor));
if (novoSensor == NULL)
{
fprintf(stderr, "Failed to allocate %zu bytes memory\n", sizeof(struct Sensor));
exit(1);
}
novoSensor->id = id;
novoSensor->intervalo = tempo;
str_copy(novoSensor->local, l, sizeof(novoSensor->local));
str_copy(novoSensor->tipo, t, sizeof(novoSensor->tipo));
novoSensor->active = 1;
novoSensor->anterior = NULL;
novoSensor->proximo = NULL;
return novoSensor;
}
static
void insereSensorFim(Sensor **Lista, Sensor *novo)
{
Sensor *atual = *Lista;
if ((*Lista == NULL))
*Lista = novo;
else
{
while (atual->proximo != NULL)
atual = atual->proximo;
atual->proximo = novo;
novo->anterior = atual;
}
}
static void print_sensor(Sensor *sensor)
{
printf("%5d %5d %1d [%-29s] [%-29s]\n", sensor->id, sensor->intervalo,
sensor->active, sensor->local, sensor->tipo);
}
static void print_sensor_list(const char *tag, Sensor *list)
{
printf("%s:\n", tag);
while (list != 0)
{
print_sensor(list);
list = list->proximo;
}
}
static void free_sensor_list(Sensor *list)
{
while (list != 0)
{
Sensor *next = list->proximo;
free(list);
list = next;
}
}
int main(void)
{
Sensor *list = 0;
print_sensor_list("Empty", list);
insereSensorFim(&list, novoSensor(10231, 23, "abc123-bothersome", "d92-x41-ccj-92436x"));
insereSensorFim(&list, novoSensor(20920, 25, "def456-troublesome", "e81-p42-ggk-81366x"));
insereSensorFim(&list, novoSensor(30476, 83, "ghi789-wearisome", "f70-q43-omm-70296x"));
print_sensor_list("After insertion", list);
gravaLista(list);
free_sensor_list(list);
list = 0;
print_sensor_list("Emptied", list);
CarregaTodos(&list);
print_sensor_list("After rereading", list);
insereSensorFim(&list, novoSensor(231, 325, "jkl012 blank laden stream", "minimum mess or cleaning"));
insereSensorFim(&list, novoSensor(6812, -11, "mno345 longer than was expected", "maximum type of untidiness at work"));
print_sensor_list("After extending", list);
free_sensor_list(list);
return 0;
}
When run, it produces the output:
Empty:
After insertion:
10231 23 1 [abc123-bothersome ] [d92-x41-ccj-92436x ]
20920 25 1 [def456-troublesome ] [e81-p42-ggk-81366x ]
30476 83 1 [ghi789-wearisome ] [f70-q43-omm-70296x ]
Emptied:
After rereading:
10231 23 1 [abc123-bothersome ] [d92-x41-ccj-92436x ]
20920 25 1 [def456-troublesome ] [e81-p42-ggk-81366x ]
30476 83 1 [ghi789-wearisome ] [f70-q43-omm-70296x ]
After extending:
10231 23 1 [abc123-bothersome ] [d92-x41-ccj-92436x ]
20920 25 1 [def456-troublesome ] [e81-p42-ggk-81366x ]
30476 83 1 [ghi789-wearisome ] [f70-q43-omm-70296x ]
231 325 1 [jkl012 blank laden stream ] [minimum mess or cleaning ]
6812 -11 1 [mno345 longer than was expect] [maximum type of untidiness at]
The output file, sensores.txt, looks like this:
10231 23 1abc123-bothersome d92-x41-ccj-92436x 20920 25 1def456-troublesome e81-p42-ggk-81366x 30476 83 1ghi789-wearisome f70-q43-omm-70296x
When split into records, that is:
10231 23 1abc123-bothersome d92-x41-ccj-92436x
20920 25 1def456-troublesome e81-p42-ggk-81366x
30476 83 1ghi789-wearisome f70-q43-omm-70296x
The integer width of 11 allows for a negative 32-bit number in each of the first two columns. If you know that the numbers are smaller, you can reduce the space used. In the scanf(), you could omit the lengths on the integer fields; it would work the same because numeric formats automatically skip white space. The printf() could add newlines; the scanning code needn't change at all because scanf() doesn't care about newlines when it is expecting a number (or a string — only %c, %[…] scan sets, and %n do not skip leading white space).
You could also arrange for some character that won't appear in the character strings (perhaps Control-A, '\1') to separate the strings. Then the scanning code could look for that and you could have variable length output.
Left to my own devices, I'd probably use a variable-length record with newline for the record delimiter, and a suitable field separator for the two strings, and a less rigid scanf() format. I'd read the lines with fgets() or POSIX
getline() and then scan the lines using
sscanf(). This would work nicely unless you can have newlines in your strings.
As I put it recently in another answer — lightly paraphrased:
Read the POSIX specification of printf() and scanf() for the full details. They do have some (clearly marked) extensions over standard C printf() and scanf(), but they serve for both POSIX and standard C. Then re-read them. And re-re-read them. And do that daily for a week, and then weekly for a month, and then monthly for a year, and then yearly ever after. It will repay the effort.
fprintf(ficheiro, "%d%d%d%30s%30s"... I suggest you put a delimiter, say coma or #. Imagine, your id is 11, intervalo is 10, when saved, it's 1110. How do you know, when reading from the file, the id is 11 instead of 1 or 111?
change insereSensorFim(&l, to insereSensorFim(l,
In insereSensorFim, you use a while loop to find the tail, it's not efficient. Let *Lista always points to the tail and skip the loop. For example,
void insereSensorFim(Sensor** tail, Sensor* novo) {
if (*tail != NULL)
{
(*tail)->proximo = novo;
novo->anterior = (*tail);
}
*tail = nova;
}
You have to separate your integers when writing to the file or else they will just look like one big number to the reading function.
You could try replacing fprintf(ficheiro, "%d%d%d%30s%30s", ...); with fprintf(ficheiro, "%d;%d;%d;%29s;%29s", ...); (29 instead of 30 because you don't write the string terminating '\0') and then should be able to read back with fscanf(ficheiro, "%d;%d;%d;%29s;%29s", ...);.
EDIT:
After writing a smaller test code and some debugging, I figured out that if you want to use %s in the formatting of fscanf() so that the white space is stripped of the end of the strings and they're \0 terminated for you, then this would work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test_save(void)
{
FILE *ficheiro;
ficheiro = fopen("sensores.txt", "r+t");
if (ficheiro == NULL) {
ficheiro = fopen("sensores.txt", "w+t");
}
fprintf(ficheiro, "%d;%d;%d;%-29s ;%-29s\n", 12, 138, 131,
"Local_test", "Tipo_test");
fprintf(ficheiro, "%d;%d;%d;%-29s ;%-29s\n", 21, 218, 213,
"Local_test_2", "Second_tipo_test");
fclose(ficheiro);
}
void test_read(void)
{
FILE *ficheiro;
ficheiro = fopen("sensores.txt", "r+t");
if (ficheiro == NULL) {
printf("no file %s\n", "sensores.txt");
return;
}
int id, intervalo, active;
char local[30], tipo[30];
while (fscanf(ficheiro, "%d;%d;%d;%29s ;%29s\n", &id, &intervalo, &active,
local, tipo) == 5) {
printf("id: %d intervalo: %d active: %d\tlocal: [%s]\ttipo: [%s]\n",
id, intervalo, active, local, tipo);
}
fclose(ficheiro);
}
int main(void)
{
test_save();
test_read();
}
Output of this test program:
id: 12 intervalo: 138 active: 131 local: [Local_test] tipo: [Tipo_test]
id: 21 intervalo: 218 active: 213 local: [Local_test_2] tipo: [Second_tipo_test]
As seen by the file writen by this test-program, each record is writen in one line:
12;138;131;Local_test ;Tipo_test
21;218;213;Local_test_2 ;Second_tipo_test
im having a problem reading from these 2 files bellow, file1 and file2, and then saving their information in 2 variables.
From the file1 i want to save the name of channels, and from the file2 i want to save the name of the users and the channel where they are signed.
I was thinking of creating 2 typedef struct(shown bellow) and then create 2 variables(shown bellow) and open the files and put the info on those lists.
I also know of another way to do it which is making a 2D array like this char[100][100], the only problem with both these solutions is that I have to impose an upper limit on the amount of the channels the list/array has.
Im not sure if these are the best ways to do it or if there is a better and easier way to do it, could you guys help?
If you guys need any more information just say so, Thanks!
Edit1: i've added the read from the file1 code that i have right now and i think it is working or so it seems but my problem/question was more of is it the right way to save the information to a variable or is there a better/easier way to do it? thanks.
Channel channels[MAX_CHANNELS];
Registration registrations[MAX_REGISTRATIONS];
typedef struct{
char name_channel[20];
int id;
} Channel;
typedef struct{
char username[50];
char name_channel[20];
} Registration;
File1:
General
SO
PCD
FBD
File2:
2016-09-26 14:00:01 paul General
2016-09-26 14:01:11 mary SO
2016-09-27 10:33:17 paul SO
2016-09-27 13:32:10 rachel General
2016-09-27 13:32:12 rachel FBD
code to read the file(i have only done the file1 yet).
File *file1 = fopen("channels.txt", "r");
if(file1==NULL){ perror("Reading error: "); exit(1); } ;
char line[100];
int i = 0;
int w=0;
for(w;w<MAX_CHANNELS;w++){
channels[w].id=-1;
strcpy(channels[w].name, "n");
}
while(fgets(line, 100, file1) != NULL){
printf("Line read: %s", line);
line[ strlen(line) -1 ] = 0;
Channel a;
strcpy(a.name , line);
a.id=1;
channels[i]=a;
i++;
}
fclose(canais);
int k;
for(k=0; k<MAX_CHANNELS; k++){
if(channels[k].id!=-1)
printf("testing var with channels: %s\n", channels[k].name);
}
Just a few tips that might help(in the code comments) :) I think its fine the way you are doing it. I think this is extensible as well since you can add a new member to a struct if you want to enrich you data further. I have seen strtok used to parse through data quite a bit. Strtok should eliminate the need for you to overwrite the newline due to the way it works.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MYSTRINGLEN (50) // In general "magic numbers"
//in code makes it hard to read, though these are fairly apparent,
//but try using #define where you can
typedef struct {
char name[MYSTRINGLEN];
// int id;
}Channel;
typedef struct {
char username[MYSTRINGLEN];
char name[MYSTRINGLEN];
} Registration;
int main(int argc, char *argv[]){
int i = 0;
//int w = 0; not needed
int k = 0;
char line[100];
Channel channels[BUFSIZ] = {{{0}}}; // num of brackets depends on num of nested data structure
Registration registrations[BUFSIZ] = {{{0}}};
/* init all to zero instead w/ bracket syntax
for (w = 0; w < BUFSIZ; w++){
channels[w].id = -1;
strcpy(channels[w].name, "n");
}
*/
FILE * file1 = fopen("channels.txt", "r");
//Many people use strtok to get done what you are doing here if you are interested
while(fgets(line,100,file1)){ // do not need to explicitly state NULL
printf("Line read %s\n", line);
line[strlen(line) -1] = 0;
//Channel a; You have already initialized a whole array of struct, just use them
strcpy(channels[i].name, line);
//a.id = 1;
//channels[i]=a;
i++;
}
fclose(file1);
for(k = 0; k < BUFSIZ; k++){
if (0 != channels[k].name[0]){ //can test if string was populated, dont need id flag
printf("testing var with channels: %s\n", channels[k].name);
}
}
return 0;
}
de here
I am terribly new at C programming.
I have stumbled upon a few answers. Some using the old syntax.
The problem is I have to create a program the will read a text file and use the read postfix lines to convert to an infix equation.
The text file would be something like this:
6 #this is the number ofcontainters
1 + 3 4 # it's no_operation_if op!=v then read value of nos mention
2 + 5 6
3 v 2.1
4 v 2.4
5 v 3.5
6 v 1.5
The C file will be read in the Ubuntu terminal where the text file is the only input and the output is the infix form.
A few suggestion as to how I will accomplish this using struct, arrays, and unions.
We were already given a format of creating struct opnode, vnode, and uniting them.
The array part I'm clueless how to transfer from reading to the array itself.
C is so weird compared to java as of this moment.
[EDIT]
Sorry I forgot to mention that this is homework... no longer postfix to infix. It's postfix to solve the equation.
Without prior knowledge of syntax and used to object oriented programming I don't know how to edit.
#include <stdio.h>
#include<stdlib.h>
#define MAXLENGTH 512
/* Codes by DocM
* struct opnode, vnode, union
*/
struct opnode{
char operator
int loperand;
int roperand;
};
struct vnode {
char letterv;
double value;
};
union {
struct opnode op;
struct vnode val;
} nodes[100];
/*node[2].op.loperand
*node[6].val.value
*/
/* This reads text file string input in terminal
* Then commands the text file be read
* etc.
* and everything else actually
*/
int main()
{
char text[MAXLENGTH];
fputs("enter some text: ", stdout);
fflush(stdout);
int i = 0;
int f = 0;
if ( fgets(text, sizeof text, stdin) != NULL )
{
FILE *fn;
fn = fopen(text, "r");
}
/* The code below should be the body of the program
* Where everything happens.
*/
fscanf (text, "%d", &i);
int node[i];
for(int j = 0; j<i;j++)
{
int count = 0;
char opt[MAXLENGTH];
fscanf(text,"%d %c", &count, &opt);
if(opt == -,+,*,)
{
fscanf(text,"%d %d", &node[j].op.loperand,&node[j].op.roperand);
node[j].op,operator = opt;
}
else
{
fscanf(text, "%lf", &node[j].val.value);
}
fscanf(text,"%lf",&f);
}
evaluate(1);
return 0;
}
/* Code (c) ADizon below
*
*/
double evaluate(int i)
{
if(nodes[i].op.operator == '+' | '*' | '/' | '-')
{
if (nodes[i].op.operator == '+')
return evaluate(nodes, nodes[i].op.loperator) + evaluate(nodes[i].op.roperator);
if (nodes[i].op.operator == '*')
return evaluate(nodes, nodes[i].op.loperator) * evaluate(nodes[i].op.roperator);
if (nodes[i].op.operator == '/')
return evaluate(nodes, nodes[i].op.loperator) / evaluate(nodes[i].op.roperator);
if (nodes[i].op.operator == '-')
return evaluate(nodes, nodes[i].op.loperator) - evaluate(nodes[i].op.roperator);
}
else
{
printf nodes[i].val.value;
return nodes[i].val.value;
}
}
I guess the basic algorithm should be:
Read the count for number of lines (not sure why this is necessary, would be easier to just keep reading for as long as there is indata provided, but whatever)
For each expected line:
Parse out the expected four sub-strings
Ignore the first, which seems to be a pointless linenumber
Print out the substrings in a shuffled order to create the "infix" look
Be done
I don't understand the part about the "v" operator, maybe you should clarify that part.
This seems a bit too much like homework for us to just blindly post code ... You need to show your own attempt first, at least.
I've got a question regarding programming and files.
while(current!=NULL)
{
if(current->Id_Doctor!='\0')
{
current=current->next;
id_doc=(current->Id_Doctor);
}
if(current->Id_Doctor=='\0')
{
id_doc=id_doc+1;
printf("%d", id_doc);
break;
}
}
fwrite(&id_doc, sizeof(char), 1, Archivo);
I dont know why but it aint writing the value of id_doc on the binary file called 'Archivo'...what could be the problem?
I added a printf of id_doc and the value was printed..I really dont know
Ok, heres the full code(more-less):
struct Medico
{
int Id_Doctor;
int Estado;
char Nombre[60];
char Clave_Acceso[20];
char Especialidad[40];
struct Medico *next;
};
void Dar_Alta_Med (int estado);
void MenuPrincipal(char enta);
int main(void)
{
char enta;
MenuPrincipal(enta);
}
void Dar_Alta_Med(int estado)
{
struct Medico * head = NULL;
struct Medico * prev, *current;
char nombre_doc[60], especialida[40], password[20];
int id_doc=0, estado_doc=1;
FILE *Archivo;
const char *md1="\n<md>\n";
const char *id_doc1="<id_doctor> ";
Archivo=fopen("md.dat", "ab+");
fwrite(md1, 1, strlen(md1), Archivo);
fwrite(id_doc1, 1, strlen(id_doc1), Archivo);
current = (struct Medico *) malloc (sizeof(struct Medico));
current->Id_Doctor=id_doc;
while(current!=NULL)
{
if(current->Id_Doctor!='\0')
{
current=current->next;
id_doc=(current->Id_Doctor);
}
else
{
id_doc=id_doc+1;
printf("%d", id_doc);
break;
}
}
fwrite(&id_doc, sizeof(id_doc), 1, Archivo);
printf("Ingresa el nombre del Doctor a dar de alta: ");
fclose(Archivo);
}
Im dying here, please help :/
Try adding fflush(Archivo); to force a write of all buffered data.
Also, this statement: if(current->Id_Doctor=='\0') really ought to be an else since there is no other thing it can be but '\0'
Three things:
Make sure your fopen is successful.
Archivo=fopen("md.dat", "ab+");
if (Archivo == NULL)
{
perror("Failed to open file Archivo");
...
}
Make sure you are checking the success of your fwrite's.
if (fwrite(&id_doc, sizeof(id_doc), 1, Archivo) < 1)
{
perror("Failed to write to file Archivo");
...
}
Make sure you have a fclose to close the file properly.
if (fclose(Archivo) != 0)
{
perror("Failed to close file Archivo");
...
}
Now that you've post a full sample of your code I guess I should ask if error checking is just left out for brevity? If not, you should think about adding it.
If you're expecting the value of id_doc to be in display format in the output file you'll have to convert the int to a string (using snprintf or similar) and write the string to the output file instead.
fwrite(&id_doc, sizeof(char), 1, Archivo);
If you defined id_doc as anything other than a char it will write \0 to the file.
Much cleaner would be:
fwrite(&id_doc, sizeof(id_doc), 1, Archivo);
If your first current is an Id_Doctor you have an endless loop.
If there is no current after your last current that is not an Id_Doctor, you get an illegal pointer derefenciation.
For your Problem:
try the flush() family.
You're passing a pointer to a FOUR-BYTE INT, but only writing ONE BYTE (the wrong byte)!
Solution: declare id_doc as "char", not "int".
You have previously written the strings "\n<md>\n" and"<id_doctor> " to the file Archivo, which seems to indicate that it is not a binary file at all, but rather an XML-style file.
In this case, what you almost certainly want is:
fprintf(Archivo, "%d", id_doc);