Why does strcat fail to concatenate two strings? - c

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.

Related

C: String Variable Loses Value After Returning From Void Function

hope you are well.
I recently started learning ADT (Abstract Data Type) in college, and I have an assignment that states the following:
Complete ADTDate adding the following primitive function:
void dayWeekStr(DatePtr date,char *buffer)// places the day of the week of the date in buffer
So in main() you define a char pointer, and send it to the function alongside the date struct. Basically what the function does is, it calls a getter to obtain the Gregorian Day in form of a number (I'm storing the dates in Julian Days); this is, from 0 (sunday) to 6 (saturday), and from that I have a switch that assigns each day in form of a string ("Tuesday") to buffer. It looks like this:
void dayWeekStr(DatePtr date,char *buffer)
{
switch (dayWeek(date))
{
case 0:
buffer="Sunday";
break;
case 1:
buffer="Monday";
break;
case 2:
buffer="Tuesday";
break;
case 3:
buffer="Wednesday";
break;
case 4:
buffer="Thursday";
break;
case 5:
buffer="Friday";
break;
case 6:
buffer="Saturday";
break;
default:
printf("ERROR\n");
break;
}
}
Back in main() you print it and that's it. My main looks like this:
int main()
{
int d=0,m=0,y=0;
printf("DD MM YYYY: ");
scanf("%d %d %d",&d,&m,&y);
printf("\n");
DatePtr date1=createDate(d,m,y);
char *s=getDinamicShortDate(date1);
char *strDay;
dayWeekStr(date1,strDay);
printf("Date: %s, %s\n",strDay,s);
date1=destroyDate(date1);
free(s);
s=NULL;
return 0;
}
So when I run it, I expect this:
DD MM AAAA: 9 9 2022
Fecha: Friday, 9/9/2022
But instead, this is the result:
DD MM AAAA: 9 9 2022
Fecha:
I really don't know what happened. I tried printing buffer's value inside the function, and it seems it stores it, but then in main it doesn't.
I also tried changing the function to
char *dayWeekStr(DatePtr date)
so it actually returns a string after the switch:
char *dayWeekStr(DatePtr date)
{
switch (dayWeek(date))
{
case 0:
return "Sunday";
break;
case 1:
return "Monday";
break;
case 2:
return "Tuesday";
break;
case 3:
return "Wednesday";
break;
case 4:
return "Thursday";
break;
case 5:
return "Friday";
break;
case 6:
return "Saturday";
break;
default:
return "-1";
break;
}
}
In main it only changes from
char *strDay;
dayWeekStr(date1,strDay);
to
char *strDay=dayWeekStr(date1);
and it does work. I believe the problem has something to do with the char pointer variable retaining its value after exiting the void function, but what's the issue here?
You have passed the value of the pointer to your function, which is stored in a local variable. Assigning to that local variable does nothing to the original pointer, but if we used string functions which use the value in that pointer, we can. For instance, using strcpy to copy the correct string into the buffer pointed to by the function argument.
#include <string.h>
#include <stdio.h>
void weekday(int day, char *buffer) {
char *days[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
if (day <= 6 && day >= 0) {
strcpy(buffer, days[day]);
}
else {
strcpy(buffer, "-1");
}
}
int main(void) {
int day = 2;
char day_of_week[20] = {0};
weekday(day, day_of_week);
printf("%s\n", day_of_week);
return 0;
}
Note also that rather than using a long switch statement or if/else, I've simply indexed into an array of strings. Remember this pattern anytime you are using a switch for a lookup with sequential numbers.

Count the spaces, commas, and points that appear in a string using switch statement in C

#include <stdioh.>
#include <string.h>
int main()
{
char a[100];
int i,contor=0;
printf("Introduceti sirul: ");
gets(a);
switch(a)
{
case ',':
contor++;
break;
case '.':
contor++;
break;
case ' ':
contor++;
break;
default:
printf("Nu exista spatii,virgule sau puncte.");
}
printf("Numarul de spatii, virgule si puncte este: %d",contor);
return 0;
}
I tried here but it gives me an error - switch quantity not an integer
Someone help?:))I can't resolve this
switch(a) won't work because a is an array (decayes to a pointer to char). You probably want something like:
char *cp= a;
while (*cp)
{
switch(*cp)
{
case ',':
contor++;
break;
// etc
}
cp++;
}
switch(expression) {
case constant-expression :
...
default : //Optional
statement(s);
}
The expression used in a switch statement must have an integral or
enumerated type, or be of a class type in which the class has a single
conversion function to an integral or enumerated type.
In other words, you cannot use the entire input string as expression to the switch statement. A perfectly working example is given by Paul Ogilvie above.

Malloc and Realloc doesn't work (C11 - CLion)

#include <stdio.h>
#include <stdlib.h>
typedef struct Ogrenciler {
int no;
char adi[50];
char soyadi[50];
double vize;
double final;
double notu;
} Ogr;
int ogrenciSayisi = 0;
void KayitEkle(Ogr *ogrenci) {
int simdikiOgr = ogrenciSayisi;
if (ogrenciSayisi == 0) {
ogrenciSayisi++;
ogrenci = (Ogr *) malloc(ogrenciSayisi*sizeof(Ogr));
} else {
ogrenciSayisi++;
ogrenci = (Ogr *) realloc(ogrenci, ogrenciSayisi * sizeof(Ogr));
}
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
printf("Adi:");
scanf("%s", ogrenci[simdikiOgr].adi);
printf("Soyadi:");
scanf("%s", ogrenci[simdikiOgr].soyadi);
printf("Vize:");
scanf("%lf", &ogrenci[simdikiOgr].vize);
printf("Final:");
scanf("%lf", &ogrenci[simdikiOgr].final);
ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
printf("Notu: %lf", ogrenci[simdikiOgr].notu);
printf("\n\n");
printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
ogrenci[simdikiOgr].notu);
}
int main() {
int c;
while (c != 5) {
printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
scanf(" %d", &c);
Ogr *ogrenci;
switch (c) {
case 1:
KayitEkle(ogrenci);
break;
case 2:
KayitSil(ogrenci);
break;
case 3:
KayitListele(ogrenci);
break;
case 4:
OrtHesapla(ogrenci);
break;
case 5:
printf("Cikiliyor");
break;
default:
printf("Gecerli bir girdi yapiniz\n");
break;
}
}
return 0;
}
As u can see, I use malloc() and realloc() for my typedef struct and I'm able to enter only one entry. When I tried adding a new entry (switch case: 1) it doesn't work and crashes after this section:
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
At first, I tried I used calloc(ogrenciSayisi*10*sizeof(Ogr)) but it was created only one space. After that, in the debugger (CLion's) after realloc section, ogrenci pointer becomes a null pointer.
Edit:
I'm not trying to return a value. As I know (int a) equals (int a[ ]) so KayitEkle(ogrenci) and void KayitEkle (Ogr ogrenci) seems legit to me. And my ogrenci should be empty in the first place so (Ogr *ogrenci=NULL) is correct as you said right?
Edit2:
In malloc section 10 is a mistake. I fixed it. I was trying something and I forgot to delete it.
You pass ogrenci pointer by value to KayitEkle(), you modify it's value inside it, yet not return it's modified value to main(). You need to pass ogrenci value using a pointer (ie. KayitEkle(&ogrenci)) or return the new value to the called (ie. ogrenci = KayitEkle(ogrenci)). Example below is with the latter.
ogrenci pointer is inside the while loop, so it will be reinitialized every time the loop runs, probably you meant to put it outside of the loop so it's value is preserved.
Local variables have undefined (read: any) value without initialization, so you need to explicitly initialize ogrenci to NULL, if you need. See Initialization.
You don't need to check for ogrenciSayisi == 0 when ogrenci == NULL, because realloc(NULL, ...) is equal to malloc(...). See realloc.
#include <stdio.h>
#include <stdlib.h>
typedef struct Ogrenciler {
int no;
char adi[50];
char soyadi[50];
double vize;
double final;
double notu;
} Ogr;
int ogrenciSayisi = 0;
// or void KayitEkle(Ogr **ogrenci) and then use *ogrenci
Ogr *KayitEkle(Ogr *ogrenci) {
int simdikiOgr = ogrenciSayisi;
ogrenciSayisi++;
ogrenci = realloc(ogrenci, ogrenciSayisi*sizeof(Ogr));
printf("No:");
scanf("%d", &ogrenci[simdikiOgr].no);
printf("Adi:");
scanf("%s", ogrenci[simdikiOgr].adi);
printf("Soyadi:");
scanf("%s", ogrenci[simdikiOgr].soyadi);
printf("Vize:");
scanf("%lf", &ogrenci[simdikiOgr].vize);
printf("Final:");
scanf("%lf", &ogrenci[simdikiOgr].final);
ogrenci[simdikiOgr].notu = (ogrenci[simdikiOgr].vize * 0.4) + (ogrenci[simdikiOgr].final * 0.6);
printf("Notu: %lf", ogrenci[simdikiOgr].notu);
printf("\n\n");
printf("Adi: %s\nNo: %d\nVize: %lf\nFinal: %lfNotu: %lf\n",
ogrenci[simdikiOgr].adi, ogrenci[simdikiOgr].no, ogrenci[simdikiOgr].vize, ogrenci[simdikiOgr].final,
ogrenci[simdikiOgr].notu);
return ogrenci;
}
int main() {
int c = 0;
Ogr *ogrenci = NULL;
while (c != 5) {
printf("\n1-\tYeni Kayit Ekle\n2-\tKayit Sil\n3-\tKayitlari Listele\n4-\tOrtalama Hesapla\n5-\tCikis\n");
scanf(" %d", &c);
switch (c) {
case 1:
ogrenci = KayitEkle(ogrenci);
break;
case 2:
ogrenci = KayitSil(ogrenci);
break;
case 3:
ogrenci = KayitListele(ogrenci);
break;
case 4:
ogrenci = OrtHesapla(ogrenci);
break;
case 5:
printf("Cikiliyor");
break;
default:
printf("Gecerli bir girdi yapiniz\n");
break;
}
}
// it's nice to free things
free(ogrenci);
return 0;
}
There are many mistakes. If you want to dynamically allocate memory with your function. A pointer of pointer must be used e.g. The instructions on the realloc line are also not correct, because if your re-allocation fails, you overwrite the old memory address and the pointer takes the same value as NULL.
And without getting off topic. You should also take precautions with the scanf function if you enter anything other than what the format expects (e.g. characters instead of numbers or vice versa), it is sure that the program will behave indeterminately, so you should anticipate this scenario.

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");
}

Trying to access string in struct causes segmentation fault

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;}

Resources