I am trying to assign different error messages to the error variable in each case by passing a pointer to the string between functions but for any reason is not working well.
Here is the code:
//This function takes a pointer to a char.
int lee(Fecha *f, char *error){
int checking;
printf("Introduzca una fecha compuesta por día, mes, y año\n");
checking = scanf("%i %i %i", &f->day, &f->month, &f->year);
printf("%d\n", checking);
switch (checking){
case 0:
//The message is assigned to the space where error points to.
*error = "Formato de fecha incorrecto. El día debe ser un entero.";
break;
case 1:
*error = "Formato de fecha incorrecto. El mes debe ser un entero.";
break;
case 2:
*error = "Formato de fecha incorrecto. El año debe ser un entero.";
break;
}
return (checking == 3);
}
int main(){
Fecha f;
//error is declared like a pointer
char * error;
int ret;
//The pointer is passed to the function as argument.
ret = lee(&f, error);
printf("%s", error);
return 0;
}
And the output:
user#console:~/$ ./Sesion1
Introduzca una fecha compuesta por día, mes, y año (o 0 0 0 para terminar el programa)
23 dfgadkfhgsñdgh 5
1
Segmentation fault
Since you want to make an output to the string, you need to pass pointer to your char*, so you need to pass error as char**.
So the function will be
int lee(Fecha *f, char **error){
int checking;
printf("Introduzca una fecha compuesta por día, mes, y año\n");
checking = scanf("%i %i %i", &f->day, &f->month, &f->year);
printf("%d\n", checking);
switch (checking){
case 0:
//The message is assigned to the space where error points to.
*error = "Formato de fecha incorrecto. El día debe ser un entero.";
break;
case 1:
*error = "Formato de fecha incorrecto. El mes debe ser un entero.";
break;
case 2:
*error = "Formato de fecha incorrecto. El año debe ser un entero.";
break;
}
return (checking == 3);
}
int main(){
Fecha f;
//error is declared like a pointer
char * error;
int ret;
//The pointer is passed to the function as argument.
ret = lee(&f, &error);
printf("%s", error);
return 0;
}
Also, you should consider not leaving pointers without value after declaration like you did with char* error in main().
The problem is, when you have a pointer that is not initialized and then you forget to give it a value or something like this, it can point anywhere within your application memory (or beyond it). Virtual memory protects you from reading and writing to others applications memory (generally speaking), but you can have a case where the pointer happens to point to some data inside your application. And if you then use this pointer to write or read, you will have unpredictable result, ranging from just displaying erroneous data to corrupting data or crashing application, which you obviously do not want.
You need to pass a pointer to your function output parameters. Since your output parameter is char*, the pointer to it is char**.
To fix, change the corresponding lines to:
int lee(Fecha *f, char **error);
// ...
ret = lee(&f, &error);
Related
I used x as an integer variable and defined this procedure that calls another procedure. The &x in choix_pion is probably causing issues to the code. How can I fix it? Or should I rather declare x as an integer pointer and fix that?
Here is the code:
In the main procedure, I defined x and y this way:
int x=0, y=0;
void tester_remplir_matrice(char matrice[][DIMENSION+1],char jeton, char *joueur, int *x, int *y ,char lettres[], char nombres[])
{
if (matrice[*x][*y]=='.') /*tester si l'intersection ets vide cad contient '.'*/
{
matrice[*x][*y]=jeton;
printf("\n");
}
else {
do {
printf("\tLa place est deja occupee!");
choix_pion(joueur,jeton,&x,&y,lettres,nombres);/*on lui demande de réexprimer
son choix où placer son pion*/
}while(matrice[*x][*y]!='.');
matrice[*x][*y]=jeton;
printf("\n");
}
}
Here is the cod of choix_pion:
void choix_pion(char *joueur,char jeton_couleur,int *x,int *y,char lettres[], char nombres[])
{
char choix[3];
char limite_lettre[3]={'A'+DIMENSION-1,'\0'};
printf("\t%s vous etes le jeton %c\n\n \tChoisissez une place XY ou X:A-I et Y:1-9 = ",joueur,jeton_couleur);
scanf("%s",choix);
printf("\n");
if ((strcmp(choix,"A")>=0) && (strcmp(choix,limite_lettre)<=0 )&& ( (strcmp(choix+1,"1")>=0) && (strcmp(choix+1,"DIMENSION")<=0))) /*vérifier si le jouer
n'a pas choisi des places hors le cadre du goban de A--I et 1--9 dans el cas de 9*9*/
{
for(int i=0;i<DIMENSION;i++)
{
if(lettres[i]==choix[0])
{
*y=i;
printf("done");
}
}
for(int i=0;i<DIMENSION;i++)
{
if (nombres[i]==choix[1])
*x=i;
}
}
else
printf("Veuillez choisir une place appartenant a l'intervalle donne!");
}
choix_pion(joueur,jeton,&x,&y,lettres,nombres)
Here you do not pass pointer only pointer to pointer (as x && y are already pointers) which was not your intention.
You need to:
choix_pion(joueur,jeton,x,y,lettres,nombres)
This is a program to register books in a library with title, writer and price.As well as calculate things such as averages, highest price book... It ran pretty well when i used a vector {struct livro Livros[1000]} instead of a pointer {struct livro *Livros}.
I used the pointers to dynamically allocate memory for the book list and everything runs fine registering the books. but when i try to calculate the average, which calls another function to main, the program crashes and the compiler(i use visual studio in my school) shows that message:
Unhandled exception at 0x00ec174c in Livraria.exe: 0xC0000005: Access violation reading location 0xcccccd94.
I tried to use the function to locate by writer instead of the average and it crashed just after i have put the string. Certainly when it used the "Livros[i].autor" to compare the strings
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define flush_toilet (fflush(stdin))
//mude o #define dependendo do seu SO
//__fpurge(stdin); "linux"
//fflush(stdin); "windows"
struct livro {
char titulo [100];
char autor [100];
float prec;
};
//register
void cadastro (int *qtd, struct livro *Livros){
int i;
Livros=NULL;
printf("Insira a quantidade de livros:");//defines the quantity(variable "qtd") of books which will pass to the main function(it worked when i used vectors)
scanf ("%i",qtd);
flush_toilet;
Livros = malloc( *qtd *sizeof(struct livro)); //allocates the memory for the list
printf ("insira os dados de cada livro:");
for (i=0;i<*qtd;i=i+1){
printf ("\n\n\ninsira o titulo:");
gets (Livros[i].titulo); //title
flush_toilet;
printf ("\ninsira o nome:");
gets (Livros[i].autor); //writer
flush_toilet;
printf ("\ninsira o preco :");
scanf ("%f",&Livros[i].prec);//price
flush_toilet;
}
}
//calculate average of prices
float media (int qtd, struct livro *Livros){
int i;
float media=0;
for (i=0;i<qtd;i=i+1){
media=media+Livros[i].prec;
}
media=media/qtd;
return media;
}
//calculate number of books above average
int qtd_acima_med (float media, struct livro *Livros, int qtd){
int acima=0,i;
for (i=0;i<qtd;i=i+1){
if(Livros[i].prec>media){
acima=acima+1;
}
}
return acima;
}
//locate a book by writer
void localizar(int qtd, struct livro *Livros){
int i;
char autor[100];
printf("\ndigite o nome do autor cujos livros deseja encontrar:\n");
gets (autor);
flush_toilet;
printf("\n");
for (i=0;i<qtd;i=i+1){
if((strcmp (autor, Livros[i].autor))==0){
puts(Livros[i].titulo);
printf("\n");
}
}
}
//finds and displays the most expensive book
void mais_caro (int qtd, struct livro *Livros ){
int i, ncaro;
float caro=0;
for (i=0;i<qtd;i=i+1){
if (Livros [i].prec>caro){
caro=Livros [i].prec;
ncaro=i;
}
}
puts (Livros[ncaro].titulo);
printf ("preco: %f\n", Livros[ncaro].prec);
}
void main (){
struct livro *Livros;
int qtd=-1, selec=1, nacima=-1;
float med=-1;
while (selec!=0){
printf ("\n\n\nDigite 0 para sair,\n 1 para cadastrar,\n 2 para calcular a media,\n 3 para calcular os livros acima da media,\n 4 para localizar o livro pelo autor,\n 5 para achar o mais caro.\n\n");
scanf("%i", &selec);
flush_toilet;
switch (selec){
case 0:
break;
case 1:{
cadastro(&qtd, Livros);
break;
}
case 2:{
if(qtd<0){
printf("erro nenhum livro cadastrado ou processo de cadastro incorreto\n");
break;
}
med=media(qtd, Livros);
printf("A media e igual a: %f \n", med);
break;
}
case 3:{
if(med<0){
printf("erro a media n foi calculada\n");
break;
}
nacima = qtd_acima_med (med, Livros, qtd);
printf("A qtd de livros com preco acima da media e: %i \n", nacima);
break;
}
case 4:{
if(qtd<0){
printf("erro nenhum livro cadastrado ou processo de cadastro incorreto\n");
break;
}
localizar(qtd, Livros);
break;
}
case 5:{
if(qtd<0){
printf("erro nenhum livro cadastrado ou processo de cadastro incorreto\n");
break;
}
mais_caro (qtd, Livros);
break;
}
}
}
free(Livros);
}
When I compile, I get the following error:
1>main.c(138) : warning C4700: uninitialized local variable 'Livros' used
This looks to be the cause of the bug. To fix, you need to return the allocated array from cadastro:
struct livro * cadastro (int *qtd){
int i;
struct livro *Livros =NULL;
printf("Insira a quantidade de livros:");//defines the quantity(variable "qtd") of books which will pass to the main function(it worked when i used vectors)
scanf ("%i",qtd);
flush_toilet;
Livros = malloc( *qtd * sizeof(struct livro)); //allocates the memory for the list
printf ("insira os dados de cada livro:");
for (i=0;i<*qtd;i=i+1){
printf ("\n\n\ninsira o titulo:");
gets (Livros[i].titulo); //title
flush_toilet;
printf ("\ninsira o nome:");
gets (Livros[i].autor); //writer
flush_toilet;
printf ("\ninsira o preco :");
scanf ("%f",&Livros[i].prec);//price
flush_toilet;
}
return Livros;
}
And then later use the return in main ():
void main (){
struct livro *Livros = NULL;
int qtd=-1, selec=1, nacima=-1;
float med=-1;
while (selec!=0){
// Snip
switch (selec){
// snip
case 1:
{
if (Livros != NULL)
{
free(Livros);
Livros = NULL;
}
Livros = cadastro(&qtd);
}
break;
You also need to check the return values of scanf() and gets() in case there is no more input or invalid input, and have a default case in the event the user enters an invalid value for selec. You should also consider replacing gets() with fgets() to prevent buffer overruns. But the immediate cause of the crash is the uninitialized variable. Presumably your compiler also reports a similar warning, and if it does, warnings like this should always be fixed.
My question refers to the while(!feof(arch)) that repeats the last registry two times. Thanks if you take some of your time to answer. I'm in first year learning basics.
The information is on an archive, so the first input shouldn't be 's' because it isn't the first time to input. Then the program list the infomation but the last registry repeats two times.
#include <stdio.h>
typedef struct{
int legajo;
char nombre[30];
int ingreso;
int pparcial;
int sparcial;
} reg_alumno;
reg_alumno funcionleer(void);
typedef FILE * archivo; //Se define el tipo de dato "archivo".
archivo arch; //Se declara una variable de archivo.
int main(void){
reg_alumno alumno,alu;
int ca,i,j=0;
char respuesta;
printf("Desea ingresar datos por primera vez?");
scanf("%c",&respuesta);
printf("Ingrese cantidad alumnos");
scanf("%d",&ca); //Pide cantidad alumnos
if(respuesta=='s'){
arch = fopen("alumnos.dat","w"); //Crear archivo para escribir, crea si no existe)
for(i=0;i<ca;i++){
alumno = funcionleer(); //Lee alumno
fseek(arch,sizeof(reg_alumno)*i,SEEK_SET); //Busca la última posición del archivo
fwrite(&alumno,sizeof(reg_alumno),1,arch); //Escribe en la última posición
}
}
else{
arch = fopen("alumnos.dat","r+");
while(!feof(arch)){
fseek(arch,sizeof(reg_alumno)*j,SEEK_SET); //Pasa de registro en registro(alumno en alumno).
fread(&alu,sizeof(reg_alumno),1,arch); //Trae a la memoria principal un alumno
printf("Legajo N %d: %s\n",alu.legajo,alu.nombre);
j++;
}
}
fclose(arch); //Cierra el archivo
}
reg_alumno funcionleer(void){ //Función leer
reg_alumno alumno;
printf("Ingrese el numero de legajo:\n");
scanf("%d",&alumno.legajo);
printf("Ingrese el nombre:\n");
scanf("%s",alumno.nombre);
return(alumno);
}
Good to check result of IO operations #WhozCraig.
The code's problem is that its prints even if fread() fails.
// No check of return value.
fread(&alu,sizeof(reg_alumno),1,arch);
printf("Legajo N %d: %s\n",alu.legajo,alu.nombre);
Code uses feof() incorrectly. Many SO posts on that.
Since OP implies code is required to use feof() by teacher: following are 2 good ways to use feof()
for (;;) {
if (fseek(arch,sizeof(reg_alumno)*j,SEEK_SET)) break;
if (fread(&alu,sizeof(reg_alumno),1,arch) == 0) break;
printf("Legajo N %d: %s\n",alu.legajo,alu.nombre);
j++;
}
// If loop quit because of EOF
if (feof(arch)) printf("Success");
else if (!ferror(arch)) printf("IO Error");
Or
for (;;) {
if (fseek(arch,sizeof(reg_alumno)*j,SEEK_SET)) break;
fread(&alu,sizeof(reg_alumno),1,arch);
if (!feof(arch)) break;
if (!ferror(arch)) break;
printf("Legajo N %d: %s\n",alu.legajo,alu.nombre);
j++;
}
I got a problem at this line c->next=var;
and my function is :
{
struct film
{
int id;
char nom[50];
char typeFilm[50];
int duree;
int dateSortie;
struct film *next;
};
#include<stdio.h>
#include<string.h>
#include "structure_film.h"
#include<stdlib.h>
void ajouter_film(struct film **h,struct film **c)
{
struct film *var;
int s, genre;
do
{
var=(struct film*) malloc(sizeof(struct film));
printf("quel est le nom du film que vous voulez ajouter ? \n");
scanf("%s",var->nom);
printf("\nquel est le type de ce film \n 1-action \n 2-aventure \n 3-romantique \n 4-comedie \n");
scanf("%d",&genre);
switch(genre)
{
case 1 :
strcpy((var->typeFilm),"action");
break;
case 2 :
strcpy((var->typeFilm),"aventure");
break;
case 3 :
strcpy((var->typeFilm),"romantique");
break;
default :
strcpy((var->typeFilm),"comedie");
}
printf("\nquel est sa duree ? \n");
scanf("%d",&var->duree);
printf("\nveuillez entrez le numero de reference de ce film : \n");
scanf("%d",&var->id);
printf("\nquel est l'annee de sortie? \n");
scanf("%d",&var->dateSortie);
if (*h==NULL)
{
*h=var;
*c=var;
}
else
{
printf("i'm in else \n");
*c->next=var;
*c=var;
var->next=NULL;
}
printf("si vous voulez ajoutez un autre film veuillez tapez 1 si non tapez 0 \n");
scanf("%d",&s);
}
while (s!=0);
}
}
The problem is the priority of the operands here:
*c->next=var;
This is evaluated as: "take the field next of the struct pointed by c, and then, deference it.". As c is not a pointer to struct film, the next field doesn't exist.
And you want: "deference the pointer c, and take the field next of the pointer that results from it." because *c is a pointer to struct film, and therefore, field next exists for it.
So, it's: (*c)->next=var; to alter the precedence order in the evaluation.
This:
*c->next=var;
Probably needs to be this:
(*c)->next=var;
At least then it might compile--who knows if it's the behavior you want!
The reason is that c is a pointer to a pointer, so you need to dereference it twice to get the next field of the struct film.
I'm new in C, and I'm trying some exercises that I found.
In one of the exercises I'm trying to use a pointer to a string (a char array), but it doesn't work. It compiles, but when is executed, it throws "stack overflow" (well, I think is an "stack overflow" because I have it in spanish).
These are the problematic lines:
//This is the variable declaration, before this, there is the "main function" declaration
char entrada[100];
char *ult=entrada;
char cantidadstr[10];
int i,j,k = 0;
int res;
scanf ("%s",entrada);
printf ("\n%s",entrada);
//Here crashes
printf ("Hola %s",ult);
while (*ult != "\0"){
//And here there's more code
Thank you in advance!!
EDIT
(I can't answer me :))
Then, I'll post a bit more of code.
When I execute, after inserting data, it throws "Violación de segmento", and google says that means Stack Overflow
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
char entrada[1001*11*101];
/*Asi tenemos el tamano maximo:
1001 por las 1000 posibles lineas, mas la primera
11 por el tamano maximo del numero (1 + 9 ceros), mas el espacio o salto de linea siguiente
101 por el numero de numeros por linea, mas el primero
*/
char *ult=entrada;
char cantidadstr[10];
int i,j,k = 0;
int res;
memset (entrada,'\0',1001*11*101);
scanf ("%s",entrada);
printf ("\n%s",entrada);
//poniendo ese print ahi arriba, ese me lo muestra, por tanto, el fallo esta en el puntero de debajo de esta linea
printf ("Hola %s",ult);
while (*ult != "\0"){
if(*ult == "\n"){
if(i != 0){
printf("\n");
}
i++;
j = 0;
}
else if(i != 0){
if(*ult == " "){
j++;
k=0;
res = atoi(cantidadstr);
printf("%d ",res*2);
//Este es el otro cambio que hablaba
cantidadstr[10] = '\0';
}
else if(j != 0){
cantidadstr[k] = *ult;
}
}
k++;
*ult++;
}
return 0;
}
This is the exact and full code, with comments in spanish for another forum. The size of "entrada" is big enough for any data send in the exercise. The "memset" is just added. The second comment shows where it crashes
Thank you for your quick answer!!
The code before the while loop is fine as it compiles and runs correctly(as far as i can think)
But the while loop has an error i'm not sure how it compiled in your case.
because you have written
while (*ult != "\0"){
which gives compiler error as
*ult is of type char
"\0" is of type const char*
you have to convert "\0" to '\0'
The following line:
cantidadstr[10] = '\0';
will write past the end of cantidadstr, which is definitely bad and most likely causing your stack overflow. If you want to null terminate cantidadstr, use cantidadstr[9]= '\0';. Arrays in C are zero based, not one based, so the first element of an array of size N starts at [0] and the last referenceable element is [N-1].