Segmentation fault when copying string to - c

Hit there!
Below is a little program I made today. It takes a table of strings, reverses all strings without reversing table, then sorts those reversed string, then reverses them back, and at last prints whole table.
I was trying really long to figure out why can't I copy 'slowo' string into place in table pointed in strcmp, but with no success. I would be happy if someone would find a way to fix Segmentation Fault in this case, but I really want to leave the method as it is below.
Thanks for your help! :)
EDIT By using debugger I determined that Segmentation Fault appears in strcpy, if that wasn't clear...
#include <stdio.h>
#include <string.h>
const int ROZMIAR=4;
char* nieposortowane[]={"basia", "zosia", "ala", "genowefa"};
int porownaj(char* a, char* b)
{
return strcmp(a,b);
}
void sortowanie(char** tablica, int N)
{
int zamienione, i;
char tmp;
do
{
zamienione=0;
for(i=0;i<N-1;i++)
if(porownaj(nieposortowane[i], nieposortowane[i+1])>0)
{
tmp=**(tablica+i);
**(tablica+i)=**(tablica+(i+1));
**(tablica+(i+1))=tmp;
zamienione=1;
}
}
while(zamienione);
}
void wypisz(char** tablica, int N)
{
int i=0;
for(i=0;i<N;i++)
printf("%s\n", *(tablica+i));
}
void odwr(char** tablica, int N)
{
int i, ln, c;
int start, koniec;
char temp;
for(i=0;i<N;i++)
{
ln = strlen(tablica[i]);
char slowo[ln];
strcpy(slowo,*(tablica+i));
start=0;
koniec=ln-1;
for(c=0;c<(ln/2);c++)
{
temp =slowo[start];
slowo[start]=slowo[koniec];
slowo[koniec]=temp;
start++;
koniec--;
}
strcpy(*(tablica+i), slowo);
}
}
int main()
{
printf("Przed sortowaniem: \n");
wypisz(nieposortowane, ROZMIAR);
odwr(nieposortowane, ROZMIAR);
sortowanie(nieposortowane, ROZMIAR);
odwr(nieposortowane, ROZMIAR);
printf("Po sortowaniu babelkowym: \n");
wypisz(nieposortowane, ROZMIAR);
return 0;
}

When allocating slowo, you should add 1 to the result of strlen when calculating the size to allocate. This is to accomodate the terminating null character, which is not included in a string's length (returned by strlen), but must be included in its total allocated size.

AFAICS, you are trying to modify the strings in:
char* nieposortowane[]={"basia", "zosia", "ala", "genowefa"};
Those are string literals stored in read-only memory; any attempt to modify them (for example, by reversing them) will fail.
I reproduced the crash with your original code. This revision of the code doesn't crash; it goes into an infinite loop in your sort code instead. I've not debugged that part of your code.
#include <stdio.h>
#include <string.h>
const int ROZMIAR=4;
char basia[] = "basia";
char zosia[] = "zosia";
char ala[] = "ala";
char genowefa[] = "genowefa";
char* nieposortowane[]={basia, zosia, ala, genowefa};
int porownaj(char* a, char* b)
{
return strcmp(a,b);
}
void sortowanie(char** tablica, int N)
{
int zamienione, i;
char tmp;
do
{
zamienione=0;
for(i=0;i<N-1;i++)
if(porownaj(nieposortowane[i], nieposortowane[i+1])>0)
{
tmp=**(tablica+i);
**(tablica+i)=**(tablica+(i+1));
**(tablica+(i+1))=tmp;
zamienione=1;
}
}
while(zamienione);
}
void wypisz(char** tablica, int N)
{
int i=0;
for(i=0;i<N;i++)
printf("%s\n", *(tablica+i));
}
void odwr(char** tablica, int N)
{
int i, ln, c;
int start, koniec;
char temp;
for(i=0;i<N;i++)
{
ln = strlen(tablica[i]);
char slowo[ln];
strcpy(slowo,*(tablica+i));
start=0;
koniec=ln-1;
for(c=0;c<(ln/2);c++)
{
temp =slowo[start];
slowo[start]=slowo[koniec];
slowo[koniec]=temp;
start++;
koniec--;
}
strcpy(*(tablica+i), slowo);
}
}
int main()
{
printf("Przed sortowaniem: \n");
wypisz(nieposortowane, ROZMIAR);
odwr(nieposortowane, ROZMIAR);
wypisz(nieposortowane, ROZMIAR);
sortowanie(nieposortowane, ROZMIAR);
wypisz(nieposortowane, ROZMIAR);
odwr(nieposortowane, ROZMIAR);
wypisz(nieposortowane, ROZMIAR);
printf("Po sortowaniu babelkowym: \n");
wypisz(nieposortowane, ROZMIAR);
return 0;
}
Sample output:
Przed sortowaniem:
basia
zosia
ala
genowefa
aisab
aisoz
ala
afewoneg
I had to interrupt after that, but you can see that the strings are reversed successfully.
You'll need to sort out a more general solution; naming the individual arrays as I did is easy for a small fixed set, but not generally. One possibility would be to use strdup() to duplicate each string into allocated space:
enum { SIZE_NPSW = sizeof(nieposortowane) / sizeof(nieposortowane[0] };
for (i = 0; i < SIZE_NPSW; i++)
nieposortowane[i] = strdup(nieposortowane[i]);

Related

Allocating dinamicaly memory problems and VLA with characters

I know I should not use c and c++ at the same time.
Can someone say why the above code are working using new?
the purpose is to remove the central character of an word given by keyboard ex: "abcde" to "abde"
I was asking if the creation of VLA is correct or not... apparently it returns what I want BUT the same main code without the other functions crashes.
I searched throw internet and i discovered that i should initialize the size ('n' in my case)of the VLA's.
Code using functions and new:
#include <stdio.h>
#include <string.h>
int citirea_sirului(char *s1, char *s2)
{
int d;
printf("Cuvantul: ");
gets(s1);
d=strlen(s1);
for(int i=0;i<d;i+=1)
{
*(s2+i)=*(s1+i);
}
return d;
}
void prelucrarea_afis_siruluiC(char *b, int d, char *a){
strcpy(a,b+(d/2)+1);
strcpy(b+(d/2),"");
strcat(b,a);
puts(b);
}
int main(){
int n;
char *cuv,*ccuv;
cuv=new char[n];
ccuv=new char[n];
n=citirea_sirului(cuv,ccuv);
printf("Dimensiunea Cuvantului: %d\n",n);
printf("\nSir prelucrat: \n");
prelucrarea_afis_siruluiC(ccuv,n,cuv);
delete[] ccuv;
delete[] cuv;
return 0;
}
Code without functions:
#include <stdio.h>
#include <string.h>
int main(){
int n;
char cuv[n], ccuv[n];
printf("Cuvantul: ");
gets(cuv);
n=strlen(cuv);
printf("Dimensiunea Cuvantului: %d",n);
for(int i=0;i<n;i++)
{
ccuv[i]=cuv[i];
}
strcpy(cuv,cuv+(n/2)+1);
strcpy(ccuv+(n/2),"");
strcat(ccuv,cuv);
printf("\nCuvantul prelucrat: %s",ccuv);
return 0;
}

Cannot make function read Double array

So i have a piece of code where i want to store 5 random names no longer than 10 letters each
void printname(char *s);
int main() {
char NAME[10][5];
int NAMECOUNTER=0;
while(NAMECOUNTER<5) {
scanf("%s",NAME[NAMECOUNTER]);
printname(&NAME[NAMECOUNTER]);
NAMECOUNTER++;
}
}
void printname(char *s) {
printf("Hello %s\n",*s);
return;
}
And lets say i want the name to print itself through function Printname. Why does this not work and prints "Hello (null)"?
One problem I see
char NAME[10][5];
Should be
char NAME[5][11];
This way you're declaring 5 name slots, each with 10 char max. The extra space is for the string null terminator.
You have
void printname(char *s) {
printf("Hello %s\n",*s);
return;
}
and you need
void printname(char *s) {
printf("Hello %s\n",s); // Took off the * from the *s
return;
}
because s is already your pointer.
I give 6 glitches to fix. See comments prefacing #<num>
#include <stdio.h>
#include <stdlib.h>
void printname(char *s);
int main() {
char NAME[5][11] = {0}; // #1 value initialize to zero
// #2 the second dimension should be 11, since 10 letters plus null-character
int NAMECOUNTER=0;
while(NAMECOUNTER<5) {
scanf("%10s",NAME[NAMECOUNTER]); // #3 %10s width specifier, limit the length of name up to 10 character long
while ( (ret = getchar()) != '\n') ; // #4 trim exceeding characters
printname(NAME[NAMECOUNTER]); // #5 no &
NAMECOUNTER++;
}
}
void printname(char *s) {
printf("Hello %s\n",s); // #6 no *
return;
}
Your code doesn't even print anything to me, it just freeze and closes. Also it's not so clear.
You are mistyping the "NAME" array inside printname. This function does not have a return value, since it has a void return, so you shouldn't type any return. Also you can save some code lines writing it before main function which is the best practice:
void printname(){
//todo
}
int main(){
return 0;
}
This is a better way to implement your function:
void printname(char Names[5][11], int index){
printf("Hello %s\n", Name[index]);
}
You could replace the while structure with for structure, since it is the best application for the purpose in that case:
Your code piece:
while(NAMECOUNTER<5) {
scanf("%s",NAME[NAMECOUNTER]);
printname(&NAME[NAMECOUNTER]);
NAMECOUNTER++;
}
You don't have to put "&" in the first argument of printname.
Best:
for(NameCounter = 0; NameCounter < 5; NameCounter++){
scanf("%s",NAME[NAMECOUNTER]);
printname(NAME[NAMECOUNTER]);
}
Also make sure to keep your code indentation clear. This is your final code:
void printname(char Names[][11], int index){
printf("Hello %s\n", Names[index]);
}
int main(){
char NAME[5][11];
int NAMECOUNTER;;
for(NAMECOUNTER = 0; NAMECOUNTER < 5; NAMECOUNTER++){
scanf("%s", NAME[NAMECOUNTER]);
printname(NAME, NAMECOUNTER);
}
}

Error with the array returning through function

I need to read a word from main function and convert the characters in UCASE if the first character is LCASE and vice versa using the user defined function.I tried ways for returning the array from function but still I am lacking some core ideas. Please debug this program and explain the way it works.
#include <stdio.h>
#include <string.h>
int* low (char str)
{
int i;
for (i=1; i<strlen(str);i++)
{
if(str[i]<91)
{
str[i]=str[i]+32;
}
else
{
}
}
return &str;
}
int* high (char str[50])
{
int i;
for (i=0; i<strlen(str);i++)
{
if(str[i]>91)
{
str[i]=str[i]-32;
}
else
{
}
}
return &str;
}
void main()
{
char str[50];
char* strl;
printf("Enter any string....\n");
scanf("%s",str);
if (str[0]<91)
{
*strl=low(str);
}
else
{
*strl=high(str);
}
printf("Converted string is %s.",*strl);
}
There is already a problem here:
So if you are saying this code is perfect and you want us to debug it and explain how (on earth) this works, then here you go.
In function int* low (char str), you have if(str[i]<91). Thats a problem right there. str is a char received as an argument, and hence str[i] is a straight compile-time error.
Another one to deal with is the return statement.
You have a statement:
return &str;
which would return the address of str, which by the way is a char, whereas function low is supposed to return a pointer to an int.
The same is applicable to high function as well.
Suggestion: Leave aside this bad code and get a beginner level C programming book first. Read it and the try some codes out of it.
A few inputs for improvement: (Which you may not comprehend)
change
void main()
to
int main(void)
Why? Refer this legendary post: What should main() return in C and C++?
Secondly, int both functions you are using strlen() in loop which will always return a fixed value. So, instead of
for (i=0; i<strlen(str);i++)
I'd suggest,
size_t strlength = strlen(str);
for (i=0; i < strlength; i++)
You can try the code and method as below:
#include <stdio.h>
#include <string.h>
char* caseConverter (char *str)
{
int i;
for (i=0; i<strlen(str);i++)
{
if(str[i]>=65 && str[i]<=90)
{
str[i]=str[i]+32; //To lower case
}
else if((str[i]>=97 && str[i]<=122))
{
str[i]=str[i]-32; //To upper case
}
else
printf("%c is not an alphabet \n",str[i]);
}
return str;
}
void main()
{
char inputStr[50]= "Stubborn";
char* opStr= caseConverter(inputStr);
printf("Converted string is %s",opStr);
}

My C program is recursing infinitely and I cannot figure out why

This program is supposed to take a name from a user and output it backwards. Our professor said we had to use recursion and I am struggling with getting to not recurse infinitely. Please help.
#include <stdio.h>
#include <string.h>
void reversedWord(char input[],int size)
{ int count;
int count2;
if(count==0) {
count2=size;
}
count2=count2-1;
char store;
store=input[count2];
input[count2]=input[count];
input[count]=store;
count=count+1;
if(count>size)
{
return;
}
return reversedWord(input,size);
}
int main()
{
char input[100];
printf("Please enter your name: ");
scanf("%s",input);
int size=strlen(input);
reversedWord(input,size);
printf("\n Your name backwards: %s \n",input);
}
First in the above code, you need to initialize your variables count and count2.
The statements int count; means that you are declaring the variable count of integer type. But it doesn't hold any value.
for this example to have the recursion working, you need to pass 3 parameters(input string, start_index,end_index) at each call to the function.
Here's the modified code to have this working
void reversedWord(char input[],int start,int end)
{
end=end-1;
char store;
store=input[end];
input[end]=input[start];
input[start]=store;
start=start+1;
if(start>=end)
{
return;
}
return reversedWord(input,start,end);
}
int main()
{
char input[100];
printf("Please enter your name: ");
scanf("%s",input);
int size=strlen(input);
reversedWord(input,0,size);
printf("\n Your name backwards: %s \n",input);
}
Since you use counters inside your recursive function they should be static, I suggest reading documentation about what static does in the C language if it is new to you.
Below is your code with working recursion, but your algorithm for word reversion contains an error. I believe you can solve it yourself with a bit of thought, so I will just give a hint - it reverses the word, but then reverses it back right again.
#include<stdio.h>
#include<string.h>
void reversedWord(char input[],int size)
{
static int count = 0;
static int count2;
if(count==0) {
count2=size;
}
count2=count2-1;
char store;
store=input[count2];
input[count2]=input[count];
input[count]=store;
count=count+1;
if(count>size)
{
return;
}
reversedWord(input,size);
return;
}
int main()
{
char input[100];
printf("Please enter your name: ");
scanf("%s",input);
int size=strlen(input);
reversedWord(input,size);
printf("\n Your name backwards: %s \n",input);
}
I think even if you assign zero to count and count2 ,this will not work because you are calling the function recursively.
So every time you call reversedWord(input,size) the values are again initialized;
> void reversedWord(char input[],int size) { int count; //initialized
> for every recursive call
> int count2; //initialized for every recursive call
> if(count==0) {
> count2=size;
> }
> count2=count2-1;
> char store;
> store=input[count2];
> input[count2]=input[count];
> input[count]=store;
> count=count+1;
> if(count>size)
> {
> return;
> }
> return reversedWord(input,size); }
A better solution would be to declare these two variables count and count2 as static.
static int count,count2 ;
by default the static variable are assigned as 0 and they share a common memory,so no new space is assigned to them and the new values get reflected on the same variable(initialized just once)

Structure printf stops the program from working

I created the following code, it compiles but it doesen't run properly. It shows some imput witch is correct, but after that, instead of printing according to the line printf(prod[0].dr[0]); it enters an "not responding" state. If you instead write printf(prod[0].dr); it works perfectly. I need to be able to print each character individualy (so I need something like printf(prod[0].dr[0]); that works)
If the question is to broad, please comment and I will try to specify every detail.
Thanks!
#include <stdio.h>
FILE *f, *g;
struct productie
{
char st, dr[20];
int realizabil;
}prod[30];
int citire(FILE *f){
char sir[100];
int i=0,j;
while(!feof(f))
{
fgets(sir,100,f);
prod[i].st=sir[0];
for(j=3;j<strlen(sir);j++)
prod[i].dr[j-3]=sir[j];
i++;
}
return i;
}
int exista(char sir[],char c)
{
int i;
for(i=0;i<strlen(sir);i++)
{
if(c==sir[i])
return 1;
}
return 0;
}
void neterminale(struct productie p[],int n, char N[])
{
int k=0;
int i,j;
for(i=0;i<n;i++)
{
if(isupper(p[i].st) && !exista(N,p[i].st))
N[k++]=p[i].st;
for(j=0;j<strlen(p[i].dr);j++)
if(isupper(p[i].dr[j]) && !exista(N,p[i].dr[j]))
N[k++]=p[i].dr[j];
}
N[k]='\0';
}
void terminale(struct productie p[],int n, char T[],char N[])
{
int k=0;
int i,j;
for(i=0;i<n;i++)
{
if(!exista(N,p[i].st) && !exista(T,p[i].st)&& p[i].st!='$')
T[k++]=p[i].st;
for(j=0;j<strlen(p[i].dr);j++)
if(!exista(N,p[i].dr[j]) && !exista(T,p[i].dr[j]) && p[i].dr[j]!='$')
T[k++] = p[i].dr[j];
}
T[k]='\0';
}
void afisare(FILE *g,int n){
int i;
for(i=0;i<n;i++)
fprintf(g,"%c -> %s",prod[i].st, prod[i].dr);
}
int main(){
char N[30];
char T[30];
int i,j,n;
f=fopen("in.txt","r");
n=citire(f);
neterminale(prod,n,N);
printf("\nNeterminalele sunt:{");
for(i=0;i<strlen(N);i++)
printf("%c ",N[i]);
printf("}");
terminale(prod,n,T,N);
printf("\nTerminalele sunt:{");
for(i=0;i<strlen(T);i++)
{
printf(" %c ",T[i]);
}
printf("}");
printf(prod[0].dr[0]); //AT THIS LINE IS THE PROBLEM
g=fopen("out.txt","w");
afisare(g,n);
fclose(f);
fclose(g);
return 0;
}
The in.txt :
S->aS
S->a
S->$
S->AB
A->b
B->c
If you want to print a string directly, you need to provide a pointer to the first character, not the first character itself:
printf(&(prod[0].dr[0]));
or
printf(prod[0].dr);
But you can't limit this to a single char (there is no nprintf function).

Resources