This is my solution to the SPOJ problem - The Next Palindrome.
I try to run it, but every time I input a no. like 9XXXXX..., it gives seg. fault, for example -
$ ./a.exe
1
99999
Palin string i++: 99999
Non-Palin String: 99999
Palin string i++: 99999
Non-Palin String: 99999
Palin string i++: 99999
Non-Palin String: 99999
Change string: 99999
9 Palin String: 99099
Palin Str j = 2
Palin Str j-- = 1
9 Palin String: 90099
Palin Str j = 1
Segmentation fault (core dumped)
My code -
#include <stdio.h>
#include <string.h>
#define MAX 1000000
int main(void)
{
unsigned int t;
scanf("%u",&t);
unsigned long int i,j,k,len,change;
char str[MAX];
while(t--){ //For every test case
scanf("%s",str);
i = 0;
change = 0;
len = strlen(str) - 1;
Recheck:
while(i <= (len/2)){ //If the input no. is a palindrome, then don't change it, else change it
if(str[i] != str[len-i]){ //Compare 1st & last digit, then 2nd & 2nd last, so on....., if not same, then...
if(str[i] > str[len-i]){ //if 1st digit > last digit,
str[len-i] = str[i]; //then make last one the same as 1st one
i++;
change++;
}
else if(str[i] < str[len-i]){ //if <, then make the last one same as 1st one,
str[len-i] = str[i]; //but also increment it's left digit,
j = (len-i) - 1; //if required, the next one too, and so on...
while(j >= 0){ //j moves from right to left (digits) in the string
if(str[j] != '9'){
str[j]++;
change++;
break;
}
else if(str[j] == '9'){
str[j] = '0';
if(j == 0){ //If the no. becomes like 9......'\0'
for(k=len+1;k>=0;k--) //and we need to increment, so shift the elements,
str[k+1] = str[k]; //and make the string: 00.......'\0
str[0] = '0'; //Next loop will make str[0] = 1 & break.
len++;
j++;
}
change++;
}
printf("\n9 Non-Palin String: %s",str);
j--;
}
if(j <= i) //if the change reaches even before from where we compared(in 1st half, that is, i),
i = j; //then change i to j, so that the no. can be checked again from j, as changes are till j.
else
i++;
}
}
else if(str[i] == str[len-i]){ //No change to a palindrome
printf("\nPalin string i++: %s",str);
i++;
}
printf("\nNon-Palin String: %s",str);
}
if(change==0){ //change == 0 means that the no. was already a palindrome
printf("\nChange string: %s",str); //so we have to find the next no. which is a palindrome
if(len%2)
j = (len/2) + 1;
else
j = len/2;
if(str[j] == '9'){ //So, if the mid char(s) is/are 9 then change the no. as we did before
while(j >= 0){
if(str[j] != '9'){
str[j]++;
change++;
break;
}
else if(str[j] == '9'){
str[j] = '0';
if(j == 0){
for(k=len+1;k>=0;k--)
str[k+1] = str[k];
str[0] = '0';
len++;
j++;
printf("\nIncrement string");
}
change++;
}
printf("\n9 Palin String: %s",str);
printf("\nPalin Str j = %lu",j);
j -= 1;
printf("\nPalin Str j-- = %lu",j);
}
printf("\nPalin to Recheck: %s",str);
i = j;
goto Recheck;
}
else{ //else, just increment the mid char/s
if(len%2){
str[j]++;
str[j-1]++;
}
else{
str[j]++;
}
}
}
printf("\n%s",str);
}
return 0;
}
I've added comments to understand the code.
For every no., 9, 99, 999, etc. it gives segmentation fault error.
It seems odd to write an answer to my own question, but still...
The problem with the solution is that the variable k is an unsigned int, so k is never < 0, hence the infinite loop.
Thanks to pm100 & Weather Vane for their help.
Not a full answer but too much for a comment.
What do you mean by "stdin input buffer"? Your typing goes into a system buffer until you press "Enter" at which point the contents are transferred to your array str by scanf(). The stream used is a predefined system stream call stdin. You can use the similar file function fscanf(stdin,"%s",str); but scanf() is more convenient (and not a very desirable method for a string anyway). However, it is very unlikely that the system buffer can hold 1 million characters, so I suggest you build the string yourself, something like this:
#include <stdio.h>
#include <conio.h>
#define MAX 1000000
int main(void)
{
char str [MAX] = ""; // initialise string to the empty string
int str_len = 0; // length (and index into) str
int c;
do {
c = getch (); // gets a char but the type returned is int
printf("%c", c);
if (c != 13)
str [str_len++] = c; // insert in array
}
while (c != 13 && str_len < MAX-1);
str [str_len] = 0; // terminate array
printf("\n%s\n", str);
printf("Length %d\n", str_len);
return 0;
}
Related
#include <stdio.h>
#include <string.h>
#define CHAR_SIZE 35
//Function to remove white space
char *remove_white_spaces(char *str)
{
int i = 0, j = 0;
while (str[i])
{
if (str[i] != ' ')
str[j++] = str[i];
i++;
}
str[j] = '\0';
return str;
}
void main()
{
int i = 0;
char str[CHAR_SIZE];
printf("\nKey in input: ");
fgetchar();
fgets(str , CHAR_SIZE, stdin);
//Remove white space
remove_white_spaces(str);
printf("%s",str);
//for (i = 0; str[i] != '\0'; ++i);
//printf("Length of the string: %d", i);
if (str[i] == '0' || str[i] == '1' )
{
printf("CORRECT");
}
else
{
printf("Wrong Input");
}
}
I want to check whether the user has type in the correct input. For example, I have key in 0 01111110 10100000000000000000000. After removing the white space, the str input became 00111111010100000000000000000000. From this str, I want to check that the user has only key in 0 and 1. The output of the result I got was correct which is shown below1.
Output of result
However, when the user key in another value including 0 and 1. The output I suppose to get is the wrong input. But I obtained Correct as the result which is shown below2.
Output of result
Additional question, How do I implement an if statement that the str has to only have 32 characters to continue otherwise it has to break and the user key has to key in 32 characters only. Can I do it in a while loop instead of an if statement so that the user would not need to run the code again?
You could use strtok to extract your characters. Also there's a flaw in your logic. it should be if (str[i] == '0' || str[i] == '1' to check if the value is '0' OR '1'. Here's a sample implementation you could refer to:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHAR_SIZE 100
int main()
{
char str[CHAR_SIZE];
printf("\n Key in value: ");
getchar();
fgets(str, CHAR_SIZE, stdin);
char *tok;
tok = strtok(str, "\n");
int i = 0;
tok++; //skip the first character which is a space
while (*tok != 0x00)
{
if (*tok <= 0x31 && *tok >= 0x30)
tok++;
else
{
printf("Wrong number input ==> %c \n", *tok);
break;
}
}
}
initialize i:
putting the equivalent of C's
int i = 0;
in your prog lang before entering the while loop should do the job.
First of all, you are checking that str[i] should be equal to 0 and equal to 1 – and that doesn't make any sense, because an element in the array can be only one value, 0 or 1; so, you should test if (str[i] == '0' || str[i] == '1').
And, before that, you should initialize i: int i = 0.
Edit you must loop over elements of the string
int check = 0;
while (str[i] != '\0')
{
if (str[i] == '0' || str[i] == '1')
i++;
else {
check = 1;
break;
}
}
if (check == 0){
print("CORRECT");
}
else {
printf("WRONG INPUT");
}
I am trying to display a matrix by taking input from a user. Here, the input is a lower triangular matrix and the user may enter the 'x' character which has to be replaced with INT_MAX.
The below program is not working correctly as the output is not matching the expected one.
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int read_int() {
char input[30] = {0};
int number;
for (int i = 0; i < sizeof(input) - 1; i++){
char c = (char)getc(stdin);
if (c == 'x' || c == 'X')
return INT_MAX;
if (c < '0' || '9' < c){
if (i == 0) continue;
input[i] = 0;
return atoi(input);
}
input[i] = c;
}
input[29] = 0;
return atoi(input);
}
int main() {
int N = read_int();
int matrix[N][N];
memset(matrix, 0, N * N * sizeof(int));
for(int i = 0; i < N; ++i){
for(int j = 0; j <= i; ++j){
int distance = read_int();
matrix[i][j] = distance;
matrix[j][i] = distance;
}
}
printf("\n");
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
printf("\n");
return 0;
}
For input:
3
x 2
x x 2
The Above program prints:
3 2147483647 2147483647
2147483647 32 2147483647
2147483647 2147483647 32
which is not expected
It should be
3 2147483647 2147483647
2147483647 2 2147483647
2147483647 2147483647 2
Update: The answers below, doesn't work for all case [except accepted one]
One such case is -
5
10
50 20
30 5 30
100 20 50 40
10 x x 10 50
it just keeps on taking input
Your logic for skipping whitespace is broken because when you eventually assign a character after skipping position 0, you will always be writing a "wanted" character at position i. That means anything already in position 0 remains.
In your case, it's undefined behavior because input[0] was originally filled with 3 on the first input where no whitespace was skipped, but in subsequent calls to your function it is uninitialized. You then go on to write a 2 into input[1] and thus by pure chance (your array from previous calls has not been overwritten on the stack and the stack is the same), you end up with the string "32" sitting in input.
What you need to do is have some way to count the actual required characters so that you write them into the array at the correct position. One naive approach would be:
int pos = 0;
for(...) {
// other logic...
// Actually write a character we want
input[pos++] = c;
}
Another way that is more like how integer input works is:
int c;
int pos = 0;
while(pos < sizeof(input) - 1 && (c = getc(stdin)) != EOF)
{
if (c == 'x' || c == 'X')
return INT_MAX;
else if (pos == 0 && isspace(c))
continue;
else if (!isdigit(c) && !(pos == 0 && (c == '-' || c == '+')))
break;
input[pos++] = c;
}
input[pos] = '\0';
return atoi(input);
I think the problem is this part of the loop:
if (c < '0' || '9' < c){
if (i == 0) continue;
input[i] = 0;
return atoi(input);
}
If you have entered 3enterx 2 as your input, then the 3 gets read successfully, and the the x gets returned as INT_MAX as intended, but in the next call to read_int, the next character in the input sequence is a space (i.e. c == ' '), and therefore it branches here. Since i == 0 at this point, the loop continues, which means i is incremented to 1, but this also means that input[0] is never changed. Most likely, input[0] contains the same value from the previous call to read_int (3), but in any case, it's undefined behaviour.
As a quick alternative, you can simply change this condition to:
if (c != ' ' && (c < '0' || '9' < c)){
This will mean input[0] will be set to a space character, which atoi will ignore.
An alternative solution could be to read in an entire line at once and tokenise the line.
My assignment: -
Write a program that replaces the occurence of a given character (say
c) in a primary string (say PS) with another string (say s).
Input: The first line contains the primary string (PS) The next line
contains a character (c) The next line contains a string (s)
Output: Print the string PS with every occurence of c replaced by s.
Test case 1: -
Input: -
abcxy
b
mf
Expected output: -
amfcxy
Test case 2: -
Input: -
Al#bal#20owL
l
LL
Expected output: -
ALL#baLL#20owL
My code below: -
#include <stdio.h>
#include <stdlib.h>
int main() {
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
fgets(S, 11, stdin); //S value input.
int i = 0;
while (PS[i] != '\0') { //Removing the '\n' from PS
if (PS[i] == '\n') {
PS[i] = '\0';
break;
}
i++;
}
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while (S[j] != '\0') {
if (S[j] == '\n') {
S[j] = '\0';
break;
}
j++;
}
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while (PS[k] != '\0') { //This loops checks the whole array for the same character mentioned in char 'c'
if (PS[k] == c) {
for (move = i; move > k; move --) { //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
PS[move + (j - 1)] = PS[move];
}
for (move = 0; move < j; move++) { //This loop adds all the characters of string S into string PS at the relevant place.
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Now the problem is that the code is not taking the input for string S.
After inputting first 2 inputs, it executes and gives a gibberish answer. I cannot figure out the bug, but what I do know is that there is some issue related to the buffer in C. Please help.
Edit: -
Thanks to #WeatherVane I have now edited the code with this: -
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
Now my code is working fine but the output is still not correct. It is sometimes failing to copy the last char from string S or giving me gibberish output.
The problem with the code was: -
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
The value of i and j are the true values of the size of string PS and string S; not i = i - 1 and j = j - 1.
Lesson learnt from this assignment: -
scanf() does not treat '\n' in any way. It WILL be left in the
buffer.
If possible use fgets and then remove '\n' from your respective array/pointer.
Be extra careful of your C buffer when dealing with chars and strings.
The final correct code is: -
#include <stdio.h>
#include <stdlib.h>
int main()
{
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if(c == '\n' || c == '\0')
{
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
int i = 0;
while(PS[i] != '\0') //Removing the '\n' from PS
{
if(PS[i] == '\n')
{
PS[i] = '\0';
break;
}
i++;
}
i = i; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while(S[j] != '\0')
{
if(S[j] == '\n')
{
S[j] = '\0';
break;
}
j++;
}
j = j; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while(PS[k] != '\0') //This loops checks the whole array for the same character mentioned in char 'c'
{
if(PS[k] == c)
{
for(move = i; move > k; move --) //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
{
PS[move + (j - 1)] = PS[move];
}
for(move = 0; move < j; move++) //This loop adds all the characters of string S into string PS at the relevant place.
{
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Warning: -
The above code is very unoptimised and unreadable. Do not use it for
long term projects. It just "works".
Any suggestions for improvements of the above code are welcomed in
the comments.
Further necessary reading material recommended if you face any issue regarding C buffer in the future: -
Read 1
Read 2
This is for Homework
I have to write a program that asks the user to enter a string, then my program would separate the even and odd values from the entered string. Here is my program.
#include <stdio.h>
#include <string.h>
int main(void) {
char *str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s", &str);
while (&str[i] < 41) {
if (i % 2 == 0) {
odd[j++] = *str[i];
} else {
even[k++] = *str[i];
}
i++;
}
printf("The even string is:%s\n ", even);
printf("The odd string is:%s\n ", odd);
return 0;
}
When I try and compile my program I get two warnings:
For my scanf I get "format '%s' expects arguments of type char but argument has 'char * (*)[41]". I'm not sure what this means but I assume it's because of the array initialization.
On the while loop it gives me the warning that says comparison between pointer and integer. I'm not sure what that means either and I thought it was legal in C to make that comparison.
When I compile the program, I get random characters for both the even and odd string.
Any help would be appreciated!
this declaration is wrong:
char *str[41];
you're declaring 41 uninitialized strings. You want:
char str[41];
then, scanf("%40s" , str);, no & and limit the input size (safety)
then the loop (where your while (str[i]<41) is wrong, it probably ends at once since letters start at 65 (ascii code for "A"). You wanted to test i against 41 but test str[i] against \0 instead, else you get all the garbage after nul-termination char in one of odd or even strings if the string is not exactly 40 bytes long)
while (str[i]) {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
if you want to use a pointer (assignement requirement), just define str as before:
char str[41];
scan the input value on it as indicated above, then point on it:
char *p = str;
And now that you defined a pointer on a buffer, if you're required to use deference instead of index access you can do:
while (*p) { // test end of string termination
if (i % 2 == 0) { // if ((p-str) % 2 == 0) { would allow to get rid of i
odd[j++] = *p;
} else {
even[k++] = *p;
}
p++;
i++;
}
(we have to increase i for the even/odd test, or we would have to test p-str evenness)
aaaand last classical mistake (thanks to last-minute comments), even & odd aren't null terminated so the risk of getting garbage at the end when printing them, you need:
even[k] = odd[j] = '\0';
(as another answer states, check the concept of even & odd, the expected result may be the other way round)
There are multiple problems in your code:
You define an array of pointers char *str[41], not an array of char.
You should pass the array to scanf instead of its address: When passed to a function, an array decays into a pointer to its first element.
You should limit the number of characters read by scanf.
You should iterate until the end of the string, not on all elements of the array, especially with (&str[i] < 41) that compares the address of the ith element with the value 41, which is meaningless. The end of the string is the null terminator which can be tested with (str[i] != '\0').
You should read the characters from str with str[i].
You should null terminate the even and odd arrays.
Here is a modified version:
#include <stdio.h>
int main(void) {
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
if (scanf("%40s", str) != 1)
return 1;
while (str[i] != '\0') {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = even[k] = '\0';
printf("The even string is: %s\n", even);
printf("The odd string is: %s\n", odd);
return 0;
}
Note that your interpretation of even and odd characters assumes 1-based offsets, ie: the first character is an odd character. This is not consistent with the C approach where an even characters would be interpreted as having en even offset from the beginning of the string, starting at 0.
Many answers all ready point out the original code`s problems.
Below are some ideas to reduce memory usage as the 2 arrays odd[], even[] are not needed.
As the "even" characters are seen, print them out.
As the "odd" characters are seen, move them to the first part of the array.
Alternative print: If code used "%.*s", the array does not need a null character termination.
#include <stdio.h>
#include <string.h>
int main(void) {
char str[41];
printf("Enter a string (40 characters maximum): ");
fflush(stdout);
if (scanf("%40s", str) == 1) {
int i;
printf("The even string is:");
for (i = 0; str[i]; i++) {
if (i % 2 == 0) {
str[i / 2] = str[i]; // copy character to an earlier part of `str[]`
} else {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:%.*s\n ", (i + 1) / 2, str);
}
return 0;
}
or simply
printf("The even string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 != 0) {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 == 0) {
putchar(str[i]);
}
}
printf("\n");
here is your solution :)
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s" , str);
while (i < strlen(str))
{
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = '\0';
even[k] = '\0';
printf("The even string is:%s\n " , even);
printf("The odd string is:%s\n " , odd);
return 0;
}
solved the mistake in the declaration, the scanning string value, condition of the while loop and assignment of element of array. :)
Quick question, What have I done wrong here. The purpose of this code is to get the input into a string, the input being "12 34", with a space in between the "12" and "32" and to convert and print the two separate numbers from an integer variable known as number. Why doesn't the second call to the function copyTemp, not produce the value 34?. I have an index_counter variable which keeps track of the string index and its meant to skip the 'space' character?? what have i done wrong?
thanks.
#include <stdio.h>
#include <string.h>
int index_counter = 0;
int number;
void copyTemp(char *expr,char *temp);
int main(){
char exprstn[80]; //as global?
char tempstr[80];
gets(exprstn);
copyTemp(exprstn,tempstr);
printf("Expression: %s\n",exprstn);
printf("Temporary: %s\n",tempstr);
printf("number is: %d\n",number);
copyTemp(exprstn,tempstr); //second call produces same output shouldnt it now produce 34 in the variable number?
printf("Expression: %s\n",exprstn);
printf("Temporary: %s\n",tempstr);
printf("number is: %d\n",number);
return 0;
}
void copyTemp(char *expr,char *temp){
int i;
for(i = index_counter; expr[i] != '\0'; i++){
if (expr[i] == '0'){
temp[i] = expr[i];
}
if (expr[i] == '1'){
temp[i] = expr[i];
}
if (expr[i] == '2'){
temp[i] = expr[i];
}
if (expr[i] == '3'){
temp[i] = expr[i];
}
if (expr[i] == '4'){
temp[i] = expr[i];
}
if (expr[i] == '5'){
temp[i] = expr[i];
}
if (expr[i] == '6'){
temp[i] = expr[i];
}
if (expr[i] == '7'){
temp[i] = expr[i];
}
if (expr[i] == '8'){
temp[i] = expr[i];
}
if (expr[i] == '9'){
temp[i] = expr[i];
}
if (expr[i] == ' '){
temp[i] = '\0';
sscanf(temp,"%d",&number);
index_counter = i+1; //skips?
}
}
// is this included here? temp[i] = '\0';
}
There are a few problems in your program:
You are using the same index into
expr and temp arrays. This works for
the first time since both will be 0
to start with but when you want to
process the 2nd number, you need to
reset the index into the temp array
back to 0. Clearly this cannot be
done using a single index. You'll
have to use two indices, i and j.
By the time you complete the
processing of the 2nd number ( 34 in
"12 34") you'll reach the end of the
string and hence the sscanf never
gets run on the second occasion ( in
general for the last occasion). So
after the for loop you need another
sscanf to extract the last number. Also you should return from the function once you've extracted the number from the string and incremented i.
You should avoid using gets() and use
fgets() instead because of security
reasons.
You can combine the multiple test for
the digits into a single test as
shown:
Something like this.
void copyTemp(char *expr,char *temp){
int i;
int j = 0;
for(i = index_counter; expr[i] != '\0'; i++){
if (expr[i] >= '0' && expr[i]<='9'){
temp[j++] = expr[i]; // copy the digit into temp..increment j.
}
else if (expr[i] == ' '){ // space found..time to extract number.
temp[j] = '\0'; // terminate the temp.
sscanf(temp,"%d",&number); // extract.
index_counter = i+1; // skip the space.
return; // done converting...return..must not continue.
}
}
// have reached the end of the input string..and still need to extract a
// the last number from temp string.
temp[j] = '\0';
sscanf(temp,"%d",&number);
}
After these changes it works as expected:
$ gcc b.c 2> /dev/null && ./a.out
12 34
Expression: 12 34
Temporary: 12
number is: 12
Expression: 12 34
Temporary: 34
number is: 34
Your approach is very fragile...if a user gives multiple spaces between the input numbers..your program will fail.
The main problem is that copyTemp writes to temp[i], but each call to copyTemp initializes i to index_counter, not to 0. This means that each call to copyTemp appends to the existing temp buffer instead of overwriting the old contents, and sscanf thus always re-reads the same string. You need to use separate indices to keep track of where to read from the input buffer and where to write to the output buffer.
Additional problems:
* Never** use ggets. Ever. Use fgets instead.
* You duplicate a lot of code in copyTemp. You instead could do:
if (expr[i] == '0' || expr[i] == '1' || ...)
or better:
if (isdigit(expr[i]))
copyTemp should take some precautions to not overflow its destination buffer. (Note that copyTemp shouldn't even need to take a destination buffer as an argument.)
You should avoid using global variables. It'd be better for copyTemp to take an argument specifying where to start reading from the input string and if it returned the index where it left off.