Trying to access string in struct causes segmentation fault - c

It's my first time posting a question here and i'll try to be as precise as I can.So i have this project and when i try to access a string in a struct it gives me a segmentation fault.
struct InfoSession {
TabNodePtr FirstTab;
TabNodePtr LastTab;
TabNodePtr CurrTab;
TabNodePtr AuxTab;
char* OpeningAddress;};
this is the struct included in the Session.c file where i have all the functions that i want to call in my main.
void SessionNewOpeningAddress(char * OpeningAddress,InfoSessionPtr Session){
scanf("%s",&OpeningAddress);
strcpy(Session->OpeningAddress,OpeningAddress);}
this is one of the functions that cause a segmentation fault(after testing i realised that each function that calls Session->OpeningAddresscause a segmentation fault.)This is my main.c where my main is included.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Session.h"
int main(int argc, char *argv[]) {
InfoSessionPtr MySession=NULL;
int option;
char OpeningAddress;
do{
printf("\n\n1. Create Session.\n\
2. Create new tab.\n\
3. Go to next tab.\n\
4. Go to previous tab.\n\
5. Move tab left.\n\
6. Move tab right.\n\
7. Set new opening address.\n\
8. Show the default opening address.\n\
9. Go to next site.\n\
10.Go to previous site.\n\
11.Show the current address.\n\
12.Close the current tab.\n\
13.Close session.\n\
14.Open a new address.\n\
Dwste thn epilogh sas(1-14, 0 gia eksodo):");
scanf("%d",&option);
switch(option)
{case 1:
SessionNew(&OpeningAddress);
MySession =&SessionNew;
printf("The Session has been created!");
break;
case 2:
SessionNewTab(MySession);
break;
case 3:
SessionTabNext(MySession);
break;
case 4:
SessionTabPrev(MySession);
break;
case 5:
SessionTabMoveLeft(MySession);
break;
case 6:
SessionTabMoveRight(MySession);
break;
case 7:
printf("Dwste nea dieuthinsi gia default\n");
SessionNewOpeningAddress(&OpeningAddress,MySession);
break;
case 8:
SessionShowOpeningAddress(MySession);
break;
case 9:
SessionSiteNext(MySession);
break;
case 10:
SessionSitePrev(MySession);
break;
case 11:
SessionAddressShow(MySession);
break;
case 12:
SessionTabClose(MySession);
break;
case 13:
SessionClose(MySession);
break;
case 14:
SessionNewAddress(&OpeningAddress,MySession);
break;
}
}while(option);
return 0;}
I've searched all over the internet but i still cant understand where the problem is.Anyone that can help me please reply as fast as you can.
Oh and the SessionNew function is here(everything works fine in this function):
InfoSessionPtr SessionNew(char * OpeningAddress){
TabNodePtr Tab;
InfoSessionPtr IS;
SiteNodePtr Site;
IS=malloc(sizeof(struct InfoSession));
Tab=malloc(sizeof(struct TabNode));
Site=malloc(sizeof(struct SiteNode));
IS->OpeningAddress=malloc(strlen(OpeningAddress)+1);
Site->Address=malloc(strlen(OpeningAddress)+1);
IS->AuxTab = NULL;
IS->CurrTab = Tab;
IS->FirstTab = Tab;
IS->LastTab = Tab;
Tab->NextTab = Tab;
Tab->PrevTab = Tab;
Site->UpTab = Tab;
Tab->CurrSite = Site;
Tab->FirstSite = Site;
OpeningAddress = "google";
strcpy(IS->OpeningAddress,OpeningAddress);
strcpy(Site->Address,IS->OpeningAddress);}

Consider this. I moved the statement OpeningAddress = "google"; before the malloc and changed it to strcpy. As I did nt have the session.h file and the other functions, i removed those references.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct InfoSession {
char* OpeningAddress;};
typedef struct InfoSession *InfoSessionPtr;
void SessionNewOpeningAddress(char * OpeningAddress,InfoSessionPtr Session){
scanf("%39s",OpeningAddress);
strcpy(Session->OpeningAddress,OpeningAddress);}
InfoSessionPtr SessionNew(char * OpeningAddress){
InfoSessionPtr IS;
IS=malloc(sizeof(struct InfoSession));
strcpy ( OpeningAddress, "google");
IS->OpeningAddress=malloc(strlen(OpeningAddress)+1);
strcpy(IS->OpeningAddress,OpeningAddress);
return IS;}
int main(int argc, char *argv[]) {
InfoSessionPtr MySession=NULL;
int option;
char OpeningAddress[40] = "g";
do{
printf("\n\n1. Create Session.\n\
2. Create new tab.\n\
3. Go to next tab.\n\
4. Go to previous tab.\n\
5. Move tab left.\n\
6. Move tab right.\n\
7. Set new opening address.\n\
8. Show the default opening address.\n\
9. Go to next site.\n\
10.Go to previous site.\n\
11.Show the current address.\n\
12.Close the current tab.\n\
13.Close session.\n\
14.Open a new address.\n\
Dwste thn epilogh sas(1-14, 0 gia eksodo):");
scanf("%d",&option);
switch(option)
{case 1:
MySession = SessionNew(OpeningAddress);
printf("The Session has been created!");
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
printf("Dwste nea dieuthinsi gia default\n");
SessionNewOpeningAddress(OpeningAddress,MySession);
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
}
}while(option);
return 0;}

Related

C - Case statement failing to compare variable

I'm a little confused with the case statement in the PrintGenre function; it passes the value correctly, but defaults to Undefined.
Little bit of background; this is ultimately becoming a (very simple) text music player, and I think I've found an easier way to do this, but just for my overall understanding I wanted to figure out why this case statement isn't functioning the way I wanted it to.
If I remove the default option, it goes to the last case option in the list.
I'm fairly new to the C language, so if there's anything I'm misunderstanding please let me know.
#include "terminal_user_input.h"
#include <stdio.h>
#include <string.h>
enum musicGenre {Pop, Alternative_Rock, Electronic, Undefined};
struct Album
{
my_string Title;
my_string Artist;
int Year;
enum musicGenre Genre;
};
my_string PrintGenre(int Genre)
{
//Variables
my_string result;
printf("%d", Genre); //outputs correctly
switch (Genre)
{
case 0:
strcpy(result.str, "Pop");
case 1:
strcpy(result.str, "Alternative Rock");
case 2:
strcpy(result.str, "Electronic");
default:
strcpy(result.str, "Undefined");
}
return result;
}
int main()
{
// Variables
struct Album Album1;
int choice;
printf("1. Pop\n");
printf("2. Alternative Rock\n");
printf("3. Electronic\n");
choice = read_integer("Please select a genre: ");
switch (choice)
{
case 1:
Album1.Genre = 0;
break;
case 2:
Album1.Genre = 1;
break;
case 3:
Album1.Genre = 2;
break;
default:
Album1.Genre = 3;
break;
}
printf("%d", Album1.Genre);
printf("The genre of Album 1 is %s", PrintGenre(Album1.Genre).str);
return 0;
}
In your code,
switch (Genre)
{
case 0:
strcpy(result.str, "Pop");
case 1:
strcpy(result.str, "Alternative Rock");
case 2:
strcpy(result.str, "Electronic");
default:
strcpy(result.str, "Undefined");
}
all the case statements bodies are missing a break; statement, which makes it a fall-through switch.
To avoid this "undesired" behaviour, you need to add a break; statement every time you want to limit the flow of program to a certain part of the body.
Quoting the example from the C11 standard, chapter ยง6.8.4.2/P7
EXAMPLE In the artificial program fragment
switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
/* falls through into default code */ << --- NOTE HERE
default:
printf("%d\n", i);
}
add break;
switch (Genre)
{
case 0:
strcpy(result.str, "Pop"); break;
case 1:
strcpy(result.str, "Alternative Rock"); break;
case 2:
strcpy(result.str, "Electronic"); break;
default:
strcpy(result.str, "Undefined");
}

Why does strcat fail to concatenate two strings?

I need to convert a number into a string. I'm a dealer and distribute cards to players. The deck contains 40 cards. Four seeds.
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *convertNum(int a); //initialization function
void main(){
char *car=convertNum(30);
printf(" number to convert 30 : %s", car);
getch();
}
char *convertNum(int a){
char *seed, *value;
switch ((a-1)/10){
case 0: seed="C"; break;
case 1: seed="Q"; break;
case 2: seed="F"; break;
case 3: seed="P"; break;
default: seed="X"; break;
}
switch(a%10){
case 0: value="10"; break;
case 1: value="01"; break;
case 2: value="02"; break;
case 3: value="03"; break;
case 4: value="04"; break;
case 5: value="05"; break;
case 6: value="06"; break;
case 7: value="07"; break;
case 8: value="08"; break;
case 9: value="09"; break;
default: value="XX"; break;
}
strcat(value, seed); /* ERROR: I need to concatenate the strings value and seed, but this isn't the right way */
return value;
}
What can I do to concatenate the strings? value and seed are pointers.
1.The pointers *value and *seed are uninitialized . They have no meomories. You need to initialize those pointers using malloc() or calloc() with some block of memory then it can hold values.
Hope this will work for you
In your function,you are assigning the pointers seed and value to string literals in the switch statements,however,what you need to do is allocate memory for these two pointers,copy strings to them using strcpy() or other standard library function,and concatenate at the end of the function.Make sure the allocated memory is big enough to hold both strings along with the '\0' character.Finally don't forget to free allocated memory when done.
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *convertNum(int a);
void main(){
char *car=convertNum(30);
printf("number to convert 30 : %s\n", car);
free(car);
getch();
}
char *convertNum(int a){
char *seed = (char*)malloc(20*sizeof(char)), *value = (char*)malloc(20*sizeof(char));
switch ((a-1)/10){
case 0: strcpy(seed,"C"); break;
case 1: strcpy(seed,"Q"); break;
case 2: strcpy(seed,"F"); break;
case 3: strcpy(seed,"P"); break;
default: strcpy(seed,"X"); break;
}
switch(a%10){
case 0: strcpy(value,"10"); break;
case 1: strcpy(value,"01"); break;
case 2: strcpy(value,"02"); break;
case 3: strcpy(value,"03"); break;
case 4: strcpy(value,"04"); break;
case 5: strcpy(value,"05"); break;
case 6: strcpy(value,"06"); break;
case 7: strcpy(value,"07"); break;
case 8: strcpy(value,"08"); break;
case 9: strcpy(value,"09"); break;
default:strcpy(value,"XX"); break;
}
strcat(value, seed);
free(seed);
return value;
}
You are pointing value and seed to string literals in your switch statements. You are not allowed to modify string literals with strcat(), because they are stored in read-only memory.
You could use malloc() in your convertNum() function to solve your problem. But then please don't forget to call free() when you no longer need a string. However, you can also provide a statically allocated array of characters from your main() function to the convertNum() function. This makes sense here, because your result strings will always have a fixed length of 3 characters:
void main(){
// Allocate an array of four characters and initialize it with zeros.
// You need 4 characters, because strings need to be zero terminated.
char car[4] = {0};
// Pass (a pointer to) the array to your covertNum() function.
convertNum(30, car);
printf(" number to convert 30 : %s", car);
getch();
}
Then you have to modify your convertNum() function as follows:
void convertNum(int a, char* result){
char *seed, *value;
switch ((a-1)/10){
[...]
}
switch(a%10){
[...]
}
strcpy(result, value); // Copy 'value' to the beginning of the 'result' array.
strcat(result, seed); // Append 'seed' to 'value'; 'result' becomes zero-terminated.
}
This gives the following output:
number to convert 30 : 10F
In case you want your output to be F10, then you have to switch value and seed in the last two lines of the convertNum() function.

Must freads be in order?

So I'm writing a code for a program with multiple menus that write different struct datas to a file and then with another menu that displays the data written in those files. Here's the code for the menu:
void displayall()
{
FILE *fp;
int choice=0;
struct depart loc = {0};
struct arrive loc1 = {0};
struct travel trav = {0};
fp=fopen("traveldat.dat","r");
while (1)
{
fread(&loc,sizeof(loc),1,fp);
fread(&loc1,sizeof(loc1),1,fp);
fread(&trav,sizeof(trav),1,fp);
double distance,time;
distance = sqrt(pow((loc1.x2-loc.x1),2)+pow((loc1.y2-loc.y1),2));
time = distance/trav.spd;
if (feof(fp))
{
break;
}
printf("\tYour departure location is : %s\n",loc.dep);
printf("\tWith the x-coordinate : %.2f\n",loc.x1);
printf("\tAnd the y-coordinate : %.2f\n\n",loc.y1);
printf("\tYour destination location is : %s\n",loc1.dest);
printf("\tWith the x-coordinate : %.2f\n",loc1.x2);
printf("\tAnd the y-coordinate : %.2f\n\n",loc1.y2);
printf("\tThe distance between these two locations is : %.2fkm\n\n",distance);
printf("\tYour preferred travel method is : %s\n",trav.mthd);
printf("\tWhich has a top speed of : %.2f km/h\n\n",trav.spd);
printf("\tYour expected travel time is : %.2f hours*\n\n",time);
printf("\t*Estimation,actual travel times may vary depending on certain conditions\n\n");
printf("\tThe system will now display the Main Menu\n\n");
}
fclose(fp);
}
The problem I'm facing is that if I go to the menu that writes loc1 or trav before the menu that writes loc, the display menu doesn't work, returns to the main menu, and then refuses to open whenver I try to access it. Is it because fread(&loc) is placed before the other freads? Or is there something I'm missing? Apologies in advance if this code is an eyesore or if I'm asking wrongly, I've only been learning programming for about a month.
Edit: loc1 and loc code as requested
void arrival_location_menu()
{
FILE *fp;
int choice=0;
struct arrive loc1;
fp=fopen("traveldat.dat","a");
printf("Please select your option (Destination location)\n");
printf("1.HOME\n");
printf("2.Andromeda Galaxy\n");
printf("3.The Library\n");
printf("4.Cprogramming.com\n");
printf("5.Return to main menu\n");
scanf("%d",&choice);
fflush (stdin);
switch (choice)
{
case 1: loc1.x2 = 3750;
loc1.y2 = 3450;
loc1.dest = "HOME";
system("CLS");
break;
case 2: loc1.x2 = 9870;
loc1.y2 = 5660;
loc1.dest = "Andromeda Galaxy";
system("CLS");
break;
case 3: loc1.x2 = 1367;
loc1.y2 = 3123;
loc1.dest = "The Library";
system("CLS");
break;
case 4: loc1.x2 = 2133;
loc1.y2 = 4767;
loc1.dest = "stackoverflow.com";
system("CLS");
break;
case 5: system("CLS");
break;
default: printf("Invalid option! Returning you to main menu...\n");
}
fwrite(&loc1,sizeof(loc1),1,fp);
fclose(fp);
return;
}
//DEPARTURE MENU
void departure_location_menu()
{
FILE *fp;
int choice=0;
struct depart loc;
fp=fopen("traveldat.dat","w");
printf("Please select your option (Departure location)\n");
printf("1.UTAR\n");
printf("2.PLUTO\n");
printf("3.IDK\n");
printf("4.UMM\n");
printf("5.Return to main menu\n");
scanf("%d",&choice);
fflush (stdin);
switch (choice)
{
case 1: loc.x1 = 1738;
loc.y1 = 1997;
loc.dep = "UTAR";
system("CLS");
break;
case 2: loc.x1 = 9850;
loc.y1 = 5675;
loc.dep = "PLUTO";
system("CLS");
break;
case 3: loc.x1 = 1363;
loc.y1 = 3125;
loc.dep = "IDK";
system("CLS");
break;
case 4: loc.x1 = 2130;
loc.y1 = 4785;
loc.dep = "UMM";
system("CLS");
break;
case 5:
system("CLS");
break;
default: printf("Invalied option!\n");
}
fwrite(&loc,sizeof(loc),1,fp);
fclose(fp);
return;
}
You seem to be asking if you can read data from anywhere in the file. Yes you can.
There is a function called fseek() to adjust the file pointer. The file pointer is the location next read from or written too.
There is also a function called ftell() to read the current file pointer. That's important if you're going to change the file pointer and want to restore it later.
I would also suggest you get into the habit of initializing variables ( even if it's to NULL or zero ), and of checking return values from functions. These two simple things can make debugging so much simpler.
I believe user #m-m has already explained the coding logic error.

C programming - enum switch case with TCHAR

I am doing a win32 program with C and I do not know how to do a enum and switch case with UNICODE.
I receive from the client a named pipe with this structure
typedef struct {
TCHAR UtilOrigem[10];
TCHAR Comando[3]; // Comando
TCHAR Argumento1[10];
}cmd;
cmd.comando have values "00", "01", "02" .....
And I want to do a switch case with cmd.comando.
Please help me.
Thanks
Carlos
Try this:
int val = _ttoi(cmd.comando);
switch (val)
{
case 0:
...
break;
case 1:
...
break;
case 2:
...
break;
...
}
Or even simpler:
int val = 10*(cmd.comando[0]-L'0')+(cmd.comando[1]-L'0');
switch (val)
{
case 0:
...
break;
case 1:
...
break;
case 2:
...
break;
...
}

C/C++ function not calling a switch structure properly

so here in my code no matter how much i change i cant get it to work properly
it is supposed to go to question. that includes scanning for a int which corresponds to an option
then its supposed to call navigate now with the option declared and work with it
but no matter what option you choose it just says
sorry
#include <stdio.h>
#include <stdlib.h>
#define OPENWINDOW "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
void question(int option)
{
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", &option);
}
void navigate(int option)
{
switch(option)
{
case 1:
printf(OPENWINDOW);
break;
case 2:
printf(OPENWINDOW);
break;
case 3:
printf(OPENWINDOW);
break;
case 4:
printf(OPENWINDOW);
break;
default :
printf("sorry");
question(option);
}
}
int main()
{
int option;
question(option);
navigate(option);
return 0;
}
Arguments are passed by value, not reference. So, your "option" arg is going to "disappear" soon after the function ends.
If you pass the "reference" to the var then you can use it to fill the caller variable. The following code and example fixes it.
void question(int *option)
{
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", option);
}
Then you call it like this:
int option;
question(&option);
// now you can use option...
Since function can return values, you could also:
int question(void)
{
int option;
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", &option);
return option;
}
// ...
int option = question();
// ...
The navigate and main using reference (pointers):
void navigate(int *option)
{
switch(*option)
{
case 1:
printf(OPENWINDOW);
break;
case 2:
printf(OPENWINDOW);
break;
case 3:
printf(OPENWINDOW);
break;
case 4:
printf(OPENWINDOW);
break;
default:
printf("sorry");
question(option);
}
}
int main(void)
{
int option;
question(&option);
navigate(&option);
return 0;
}
You need to pass option as pass-by-reference. Pass the address of option to question() and update there.
Refer the modified code.
void question(int *option)
{
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", option);
}
call the question() as,
question(&option);
You need to either pass pointer of option to question or return it from the function question.
In your case value of option in main() is not changing when you read it in question(). Update your code as
int question()
{
int option;
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", &option);
return option;
}
int main()
{
int option;
option = question(option);
navigate(option);
return 0;
}
You are passing "option" as call by value. Hence whatever you pass to question(). Would be lost.
Either, you return "option" from question() and pass this to navigate().
#include <stdio.h>
#include <stdlib.h>
#define OPENWINDOW "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
int question()
{ int option;
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", &option);
return option;
}
void navigate(int option)
{
switch(option)
{
case 1:
printf(OPENWINDOW);
break;
case 2:
printf(OPENWINDOW);
break;
case 3:
printf(OPENWINDOW);
break;
case 4:
printf(OPENWINDOW);
break;
default :
printf("sorry");
question(option);
}
}
int main()
{
int option;
option = question();
navigate(option);
return 0;
}
~
If you do not want to use pass-by-reference, you can use pass-by-value which you are using in your code. It only needs to be implemented properly. You can change your "void question" to return a value by changing the void to "int" and issuing a return statement before the end of question function. Check code below:
#include <stdio.h>
#include <stdlib.h>
#define OPENWINDOW "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
int question()
{
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", &option);
return i;
}
void navigate(int option)
{
switch(option)
{
case 1:
printf(OPENWINDOW);
break;
case 2:
printf(OPENWINDOW);
break;
case 3:
printf(OPENWINDOW);
break;
case 4:
printf(OPENWINDOW);
break;
default :
printf("sorry");
question(option);
}
}
int main()
{
int option;
option = question(option);
navigate(option);
return 0;
}
You are passing the variable option by value question(option)
You should pass option varible by reference
void question(int *option)
{
printf("What Would You Like To Do?\n");
printf("\t1.Add A Reminder\n\t2.View Reminders\n\t3.Manage Current Reminders\n\t4.Settings\n");
scanf("%i", option);
}
void navigate(int *option)
{
switch(*option)
{
case 1:
printf(OPENWINDOW);
break;
case 2:
printf(OPENWINDOW);
break;
case 3:
printf(OPENWINDOW);
break;
case 4:
printf(OPENWINDOW);
break;
default :
printf("sorry");
question(option);
}
int main()
{
int option;
question(&option);
navigate(&option);
return 0;
}
For more information regarding this have a look at this link Difference between call by reference and call by value
Because the variable option only pass its value into function question(), the variable option's value indeed is unchanged, so, maybe you should return the value of option in the function question()

Resources