Why I am getting a SIGSEGV error for this program? - c

I am trying to make a reverse Polish printer on an online coding website which can perform the following operation-
Inputs:
(a+(b*c))
((a+b)*(z+x))
((a+t)*((b+(a+c))^(c+d)))
Outputs:
abc*+
ab+zx+*
at+bac++cd+^*
This is my code:
#include <stdio.h>
#include <string.h>
char pop(int t);
void push(int c, int t);
char a[100][400];
int main()
{
int z;
scanf("%d", &z);
int i = 0;
int q = z;
while (q-- > 0)
{
scanf("%s",&a[i][0]);
int t;
for (t = 0; t < strlen(a[i]); t++) //loop to put the values and signs in the 2 stacks
{
if ((a[i][t] == '*') || (a[i][t] == '+') || (a[i][t] == '-') || (a[i][t] == '^'))
{
push(a[i][t], 2);
}
else if (a[i][t] == ')')
{
int y = pop(2);
push(y, 1);
}
else
{
push(a[i][t], 1);
}
}
int k = 0;
char c;
while ((c = pop(1)) !='\0') //loop to put elements in the array v
{
if (c != '(')
{
a[i][k++] = c;
}
}
a[i][k--] = '\0';
int m;
for (m=0; m != k; m++, k--)
{
char t = a[i][m];
a[i][m] = a[i][k];
a[i][k] = t;
}
}
int p;
for (p = 0; p <z ; p++)
printf("%s\n",a[i]);
return 0;
}
char ac[400];
char as[400];
int ic = 0;
int is = 0;
void push(int c,int t)
{
if (t == 1 && ic != 400)
ac[ic++] = c;
else if (t == 2 && is != 400)
as[is++] = c;
}
char pop(int t)
{
if (t == 1 && ic != 0)
return ac[--ic];
if (t == 2 && is != 0)
return as[--is];
return '\0';
}
On compiling this code I am getting a SIGSEGV error.I don't know whats the mistake in this code.Please help

I don't know why you are getting SIGSEGV. However, I see couple of errors in your code.
You are using scanf("%s",&a[i][0]); but i is never changed from its initial value of 0. I suggest changing
while (q-- > 0)
to
for ( i = 0; i < z; ++i )
You are printing a[i] even though you are using p as the for loop index in
for (p = 0; p <z ; p++)
printf("%s\n",a[i]);
That's easily fixed by changing the second line to:
printf("%s\n",a[p]);
In your input, you didn't include the value of z. I hope that is an error in creating the post and that you have the value of z in your input.
With those changes, I don't see any problem in my environment. I tested using gcc 4.7.3. Not sure fixing those will fix the problem in your environment.

Related

why can't my program recognize similar words in a string?

I want to write a program that will take an input T. In the next T lines, each line will take a string as an input. The output would be how many ways the string can be reordered.
#include <stdio.h>
#include <stdlib.h>
int main() {
int T, i, l, count = 1, test = 0, word = 0, ans;
char line[200];
scanf("%d", &T);
for (i = 0; i < T; i++) {
scanf(" %[^\n]", line);
l = strlen(line);
for (int q = 0; q < l; q++) {
if (line[q] == ' ') {
word++;
}
}
ans = fact(word + 1);
word = 0;
for (int j = 0; j < l; j++) {
for (int k = j + 1; k < l; k++) {
if (line[k] == ' ' && line[k + 1] == line[j]) {
int m = j;
int n = k + 1;
for (;;) {
if (line[m] != line[n]) {
break;
} else
if (line[m] == ' ' && line[n] == ' ') {
test = 1;
break;
} else {
m++;
n++;
}
}
if (test == 1) {
count++;
ans = ans / fact(count);
count = 0;
test = 0;
}
}
}
}
printf("%d\n", ans);
}
}
int fact(int n) {
if (n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
Now, in my program,
my output is like this:
2
no way no good
12
yes no yes yes no
120
if T = 2 and the 1st string is no way no good, it gives the right output that is 12 (4!/2!). That means, it has identified that there are two similar words.
But in the 2nd input, the string is yes no yes yes no. that means 3 yes and 2 nos. So the and should be 5!/(3!2!) = 10. But why is the answer 120? and why can't it recognize the similar words?
The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ') but this test fails to identify a duplicate that occurs with the last word because line[n] is '\0', not ' '.
Note these further problems:
you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count); only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans to be divided by 23 = 8, instead of 3! = 6.
you should protect against buffer overflow and detect invalid input with:
if (scanf(" %199[^\n]", line) != 1)
break;
the range of type int for ans is too small for a moderately large number of words: 13! is 6227020800, larger than INT_MAX on most systems.
The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.
Here is a modified version using this approach:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmpstr(const void *p1, const void *p2) {
char * const *pp1 = p1;
char * const *pp2 = p2;
return strcmp(*pp1, *pp2);
}
unsigned long long factorial(int n) {
unsigned long long res = 1;
while (n > 1)
res *= n--;
return res;
}
int main() {
int T, i, n, begin, count;
unsigned long long ans;
char line[200];
char *words[100];
if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
return 1;
while (T --> 0) {
if (!fgets(line, sizeof line, stdin))
break;
n = 0;
begin = 1;
for (char *p = line; *p; p++) {
if (isspace((unsigned char)*p)) {
*p = '\0';
begin = 1;
} else {
if (begin) {
words[n++] = p;
begin = 0;
}
}
}
qsort(words, n, sizeof(*words), cmpstr);
ans = factorial(n);
for (i = 0; i < n; i += count) {
for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
continue;
ans /= factorial(count);
}
printf("%llu\n", ans);
}
return 0;
}

Why atof function does not work properly?

I am coding in C in a university course and we got a project to take equations from the user and give solutions for matrices etc...
My problem is that I am trying to use atof() function and for a reason I can't find in the same loop once it works and the other times it doesn't.
I have tried already other functions to replace atof like strtod but it doesn't work as well.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdbool>
void main()
{
int num, check = 0,i,j,k=0,len1=0;
char equ[80],tempx[20],tempy[20], tempz[20], tempd[20];
double *x, *y, *z, *d;
printf_s("Number of equations (1-3): ");
scanf_s("%d", &num);
getchar();
while (check == 0) //a check to see if we got a number between 1-3.
{
if (num > 0 && num < 4)
check = 1;
else
{
printf_s("Please enter a number between 1-3.\n");
printf_s("Number of equations (1-3): ");
scanf_s("%d", &num);
}
}
x = malloc(sizeof(double)*num);
if (!x) exit(1);
y = malloc(sizeof(double)*num);
if (!y) exit(1);
z = malloc(sizeof(double)*num);
if (!z) exit(1);
d = malloc(sizeof(double)*num);
if (!d) exit(1);
for (i = 0; i < num; i++) //getting the equations and putting them into the matrix
{
printf_s("Enter equation %d: ", i + 1);
gets_s(equ, sizeof(equ));
len1 = strlen(equ);
for (j = 0; j <len1 ; j++)
{
if (equ[j] == 'x')
{
k = 0;
while ((equ[j-k] != '+' || equ[j-k] != '-') && j-k>=0)
{
tempx[j-k] = equ[j-k];
k++;
}
x[i] = atof(tempx);
}
else if (equ[j] == 'y')
{
k = 0;
while ((equ[j-k] != '+' || equ[j-k] != '-') && j - k >= 0)
{
tempy[j-k] = equ[j-k];
k++;
}
y[i] = atof(tempy);
}
else if (equ[j] == 'z')
{
k = 0;
while ((equ[j - k] != '+' || equ[j - k] != '-') && j - k >= 0)
{
tempz[j-k] = equ[j - k];
k++;
}
z[i] = atof(tempz);
}
else if (equ[j] == '=')
{
k = 0;
while (equ[j+k])
{
tempd[k] = equ[j + k];
k++;
}
d[i] = atof(tempd);
}
}
}
free(x);
free(y);
free(z);
free(d);
}
I expected to get the same result in d[i] as I did in x[i] but every time I try to print d[i] I get 0.0000. When I tried the function _strrev on tempd inside atof I got the reverse result inside d[i].
So the problem was that in the last loop i inserted a string that start with "=" and not a number. Apparently atof() doesn't work when the first char is not a number.

C program palindrome game

I'm new in c programming and i'm trying to make a palindrome game. I've given the code below but there is some mistake I'm making and doesn't run can you please give me a hand. Thank you.
The point of the game is to give number to an array, then change with the keys a,d,x,w and try to make it palindrome.
If there is any error can u please give me some advice ?
This is pal.c
#include <stdio.h>
#include "visible.h"
//--------------------------------------------------
// is_pal
//--------------------------------------------------
void print_status(int a[], int* p, int num_mov);
int is_pal(int a[])
{
int b[6];
int i, j;
j = 0;
for (i = 5; i >= 0; i--)
{
b[j] = a[i];
j++;
}
for (i = 0; i <= 5; i++)
{
if (a[i] != b[i]) {
return 0;
}
}
return 1;
}
//--------------------------------------------------
// process_movement
//--------------------------------------------------
void process_movement(int a[], int* p, int num_mov, char c)
{
char d;
d=c;
if(d == 'd')
{
p = a+1;
num_mov++;
print_status(a,p,num_mov);
}
else if(d == 'a')
{
p = a-1;
num_mov++;
print_status(a,p,num_mov);
}
else if(d == 'x')
{
p = malloc(6*sizeof(int));
a = p-1;
num_mov++;
}
else if(d == 'w')
{
p = malloc(6*sizeof(int));
a = p+1;
num_mov++;
}
}
//--------------------------------------------------
// print_status
//--------------------------------------------------
void print_status(int a[], int* p, int num_mov)
{
printf("Number = ");
int i;
for( i = 0; i < 6; i++)
{
printf("%d ", a[i]);
}
printf("\n Number moves = ");
printf("%d", num_mov);
//printf("\n ","%s%", "Pointer is at position ");
printf("%d", *p);
printf("\n");
}
void user_game_palindrome(int pal_num)
{
int a[5];
int i,num_mov;
num_mov = 0;
i = 5;
while (pal_num != 0) {
a[i] = pal_num % 10;
pal_num = pal_num / 10;
i--;
}
int *p = a;
while (is_pal(a) == 1)
{
char c;
print_status(a,p,num_mov);
c = ask_for_command();
process_movement(a,p,num_mov,c);
}
}
This is ex1.c
#include "pal.h"
int main() {
int pal_num = 123342;
user_game_palindrome(pal_num);
return 0;
}
visible.c
#include "visible.h"
#include "conio.h"
//--------------------------------------------------
// gen_num
//--------------------------------------------------
int gen_num(int lb, int ub) {
int num = (rand() % (ub - lb)) + lb;
return num;
}
/* Note: Do not forget to include the following instruction at the beginning of your main() method:
srand(time(NULL));
*/
//--------------------------------------------------
// my_getchar
//--------------------------------------------------
char my_get_char() {
char my_char;
int b = 0;
char dummy_char;
my_char = getchar();
while (b == 0) {
dummy_char = getchar();
if (dummy_char == '\n')
b = 1;
}
return my_char;
}
this is the visible.c ( my teacher told me to include it)
Your conversion from int to array is wrong
for (i = 0; i < 4; i++) {
a[i] = pal_num%10;
pal_num = pal_num % 10;
}
Here, why would this loop end when i is 4. It should go till pal_num is 0. And pal_num = pal_num % 10; should be pal_num = pal_num / 10;
Try something like
i = 0;
while (pal_num != 0) {
a[i] = pal_num % 10;
pal_num = pal_num / 10;
i++;
}
NOTE: Be aware, that this would essentially reverse your int and store in the array.
There's a lot going wrong in your code and you still haven't fixed many things which have been pointed out by others.
as to remove the unnecessary creating of the array b, is_pal can be defined as:
int is_pal(int a[])
{
int i;
for (i = 0; i < 3; ++i)
{
if (a[5-i] != a[i])
return 0;
}
return 1;
}
process_movement doesn't have a case where d == 'w'
user_game_palindrome should have the while loop checking (is_pal(a) == 0)
And you should apply the changes that were suggested by #Haris

Reverse Polish converter

I am trying to make a reverse Polish printer which can perform the following operation-
Inputs:
(a+(b*c))
((a+b)*(z+x))
((a+t)*((b+(a+c))^(c+d)))
Outputs:
abc*+
ab+zx+*
at+bac++cd+^*
This is my code:
#include <stdio.h>
#include <string.h>
char pop(int t);
void push(int c, int t);
int main()
{
int z;
scanf("%d", &z);
char *a[100];
int i = 0;
int q = z;
while (q-- > 0)
{
char v[400];
scanf("%s", &v);
int t;
for (t = 0; t < strlen(v); t++) //loop to put the values and signs in the 2 stacks
{
if ((v[t] == '*') || (v[t] == '+') || (v[t] == '-') || (v[t] == '^'))
{
push(v[t], 2);
}
else if (v[t] == ')')
{
int y = pop(2);
push(y, 1);
}
else
{
push(v[t], 1);
}
}
int k = 0;
char c;
while ((c = pop(1)) !='\0') //loop to put elements in the array v
{
if (c != '(')
{
v[k++] = c;
}
}
v[k--] = '\0';
int m;
for (m=0; m != k; m++, k--) //for reversing the string
{
char t = v[m];
v[m] = v[k];
v[k] = t;
}
a[i++] =v;
printf("%s",a[i - 1]);
}
int p;
for (p = 0; p <z ; p++) //printing the elements
printf("%s\n",*a[p]);
return 0;
}
char ac[400];
char as[400];
int ic = 0;
int is = 0;
void push(int c,int t)
{
if (t == 1 && ic != 400)
ac[ic++] = c;
else if (t == 2 && is != 400)
as[is++] = c;
}
char pop(int t)
{
if (t == 1 && ic != 0)
return ac[--ic];
if (t == 2 && is != 0)
return as[--is];
return '\0';
}
But it is not even inputting properly and I am not able to figure out what are the mistakes in this code.Please help to figure out what are the problems.
after inputing the no of test cases i.e.int z and first line if input
it crashes
This is due to the
printf("%s\n",*a[p]);
as BLUEPIXY noticed, *a[p] is a char; but %s expects a char *, thus you need
printf("%s\n", a[p]);
and regarding v is out of scope, the crucial factor is not the scope (visibility), but the storage duration (lifetime) of v - its lifetime ends when execution of the block with which it is associated ends, and the value of a pointer a[i] to it becomes indeterminate; by changing
a[i++] =v;
to
a[i++] = strdup(v);
you can remedy that.

using array to store big numbers

i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.

Resources