Why does the online judge fail to accept it? - c

When I submit a code in the below given format the online judge(of Codechef ) does not accept it:
#include<stdio.h>
int main()
{
int length,test;
char check[26]="zyxwvutsrqponmlkjihgfedcba";
scanf("%d",&test);
while(test--){
scanf("%d",&length);
if(length%25 != 0)
printf("%s",check+25-(length%25));
length/=25;
while(length--)
{
printf("%s",check);
}
printf("\n");
}
return 0;
}
However when I submit the code in the one given below it is readily accepted. Here all I've done is just made the char array from local to global. Can anyone gimme the reasons for it.
#include<stdio.h>
char check[26]="zyxwvutsrqponmlkjihgfedcba";
int main()
{
int length,test;
scanf("%d",&test);
while(test--){
scanf("%d",&length);
if(length%25 != 0)
printf("%s",check+25-(length%25));
length/=25;
while(length--)
{
printf("%s",check);
}
printf("\n");
}
return 0;
}
Link to the question for which it was used:
http://www.codechef.com/problems/DECSTR

check needs 27 chars to store the string literal (including terminating null) you assigned to it, not 26. Reading off the end is UB, but what's likely happening is in the global-scope version, the next byte happens to be 0, but the local-scope version, the next byte is non-zero, causing an access violation.

You cannot use check (in either version) with "string" functions.
check does not have a terminating NUL byte ('\0') so you invoke Undefined Behaviour.
Hint: leave off the size of the array when initializing with a string literal.
char check[] = "zyxwvutsrqponmlkjihgfedcba"; // compiler determines size automagically

Related

String terminator issues

If I type in this code, it compiles and runs (I use GCC)
#include<stdio.h>
int main()
{
char sentence[8]="September";
printf("The size of the array is %d \n",sizeof(sentence));
printf("The array is %s \n",sentence);
}
and gives the output
The size of the array is 8
The array is Septembe
How is this working? A string terminator is needed for C to know that the string has ended. How is the array worth 8 bytes of space and knows where to stop?
By passing a non-NUL-terminated string to printf("%s"), you're invoking undefined behavior.
By its very nature, the result is undefined. It may seemingly "work" (like you're seeing).
As others have explained, what's probably happening is that there happens to be a zero byte after your string, which stops printf from going further. However, if you were to add more stuff around that variable, you'd probably see different behavior:
#include<stdio.h>
int main(void)
{
char sentence[8] = "September"; // NOT NUL TERMINATED!
char stuff[] = "This way is better";
printf("%s\n", sentence); // Will overrun sentence
return 0;
}

Why is strlen causing a segmentation fault in C?

(Warning) Yes this is a part of an assignment I am working on, but I am completely desperate at this point and NO I am not looking for you guys to solve it for me, but any hint would be much appreciated!(/Warning)
I am pretty much trying to make an interactive menu, the user is meant to input an expression (For example "5 3 +") and the program should detect that it's in postfix notation, unfortunately I have been getting segmentation fault errors and I suspect they have something to do with the use of the strlen function.
EDIT: I was able to make it work, first the char expression[25] = {NULL}; line
becomes char expression[25] = {'\0'};
And when calling the determine_notation function I removed the [25] from the array I am passing like so:
determine_notation(expression, expr_length);
Also the input[length] part I changed to input[length-2] since like mentioned in a previous comment, input[length] == '\0' and input[length--] == '\n'.
All in all thanks for all the help!
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int determine_notation(char input[25], int length);
int main(void)
{
char expression[25] = {NULL}; // Initializing character array to NULL
int notation;
int expr_length;
printf("Please enter your expression to detect and convert it's notation: ");
fgets( expression, 25, stdin );
expr_length = strlen(expression[25]); // Determining size of array input until the NULL terminator
notation = determine_notation( expression[25], expr_length );
printf("%d\n", notation);
}
int determine_notation(char input[25], int length) // Determines notation
{
if(isdigit(input[0]) == 0)
{
printf("This is a prefix expression\n");
return 0;
}
else if(isdigit(input[length]) == 0)
{
printf("This is a postfix expression\n");
return 1;
}
else
{
printf("This is an infix expression\n");
return 2;
}
}
You probably got a warning explaining that you are converting a char to a pointer in this call:
expr_length = strlen(expression[25]);
// ^^^^
This is the problem - your code is referencing a non-existent element past the end of the array (an undefined behavior) and tries to pass it to strlen.
Since strlen takes a pointer to the beginning of the string, the call needs to be
expr_length = strlen(expression); // Determining size of array input until the NULL terminator

Given a string write a program to generate all possible strings by replacing ? with 0 and 1?

I have written this code it is working fine for a?b?c? and a?b?c?d? but for a?b?c?d?e? it is giving one additional garbage value at the end. At the end of s there is '\0' character attached then why and how is it reading that garbage value. I tried to debug it by placing printf statements in between the code but couldn't resolve it. please help.
#include<stdio.h>
void print(char* s,char c[],int l)
{
int i,j=0;
for(i=0;s[i]!='\0';i++)
{
if(s[i]=='?')
{
printf("%c",c[j]);
j++;
}
else
printf("%c",s[i]);
}
printf(", ");
}
void permute(char *s,char c[],int l,int index)
{
if(index==l)
{
print(s,c,l);
return;
}
c[index]='0';
permute(s,c,l,index+1);
c[index]='1';
permute(s,c,l,index+1);
}
int main()
{
char s[10],c[10];
printf("Enter a string.");
scanf("%s",s);
int i,ct=0;
for(i=0;s[i]!='\0';i++)
{
if(s[i]=='?')
ct++;
}
permute(s,c,ct,0);
return 0;
}
My output was like this :-
a0b0c0d0e0♣, a0b0c0d0e1♣,
...and so on.
As we can see from your code, with an array defined like char s[10] and the input being
a?b?c?d?e?
is too big an input to be held in s along with the null-terminator by
scanf("%s",s);
You need to use a bigger array. Otherwise, in attempt to add the terminating null after the input, the access is being made to out-of-bound memory which invokes undefined behaviour.
That said, never allow unbound input to the limited-sized array, always use the field-width to limit the input length (in other words, reserve the space for null-terminator), like
scanf("%9s",s);
The code is producing the correct output here, but note that it has undefined behavior for strings of size greater than or equal to 10 chars, because that's the size of your buffer.
So, for a?b?c?d?e? you need a buffer of at least 11 characters, to account for the null terminator. You should make s bigger.
See actually in C what happens in String is that everytime it appends a '\0' character at last.
Now notice in C there is nothing called string.
It's array of characters.
So if you have defined like this-
char s[10]
This actually accepts an array of less than of 9 characters as the last one will be the '\0' character.
If you add more than 9 character it will give erroneous output.

'Scanf' for a String - Program crashing?

Why is this crashing when I input the string? I don't think I'm reading in the string right but the program gives me an error on the first 'scanf.' The program should be correct but this is C not C++. Most help that I could find was for C++.
//Andrei Shulgach
//April 27th, 2015
/*A string is a palindrome if it can be read forward and backward with the same
meaning. Capitalizations and spacing are ignored.*/
#include <stdio.h>
#include <stdlib.h>
int newStrCmp (const char *string1, const char *string2);
int main()
{
//Local Declarations
int dummy, value;
char string1[100],string2[100];
printf("Please enter the 1st string: ");
scanf_s("%99s", string1[100]);
printf("\nPlease enter the 2nd string: ");
scanf_s("%99s", string2[100]);
//Call Function and get value
value = newStrCmp(string1, string2);
if (value == 0)
printf("The strings are equal.\n");
else
printf("The strings are not equal.\n");
scanf_s("%d",&dummy);//Keep Window Open
return 0;
}
int newStrCmp (const char *string1, const char *string2)
{
//Local Declarations
int value = 0;
while (string1[value] == string2[value])
{
if (string1[value] == '\0' || string2[value] == '\0')
break;
value++;
}
if (string1[value] == '\0' && string2[value] == '\0')
return 0;
else
return -1;
}
You must enable all compiler warnings that you can get from your compiler; the above code shouldn't have compiled.
This:
scanf_s("%99s", string1[100]);
invokes undefined behavior since it indexes outside the 100-character string1 array. Remember that C arrays are indexed from 0. It also fails to comply with scanf_s()'s requirement that the size be specified for all string conversions.
It then probably1 causes more undefined behavior, when scanf_f() interprets a single character as a buffer address where input is to be stored (assuming the call happens, of course).
This is not valid code.
It should simply pass the address of the first character in the array:
scanf_s("%99s", string1, sizeof string1);
Here, string1 is the same as &string1[0]; the name of an array evaluates to the address of its first element in many contexts. We then use sizeof string1 as the third argument to specify the size of the string1 buffer, which is required.
1 You cannot reason about what happens after undefined behavior has happened with any certainty.
The issue is you are 'scanf'ing into index 100 of your length 100 buffer, i.e. out-of-bounds.
scanf_s("%99s", string1);
Also your comparison would be safer as a for loop that ensures value is less than 100, rather than a while loop.
In the future, please include the error message.

Find String Length without recursion in C

#include<stdio.h>
#include<conio.h>
void main()
{
int str1[25];
int i=0;
printf("Enter a string\n");
gets(str1);
while(str1[i]!='\0')
{
i++;
}
printf("String Length %d",i);
getch();
return 0;
}
i'm always getting string length as 33. what is wrong with my code.
That is because, you have declared your array as type int
int str1[25];
^^^-----------Change it to `char`
You don't show an example of your input, but in general I would guess that you're suffering from buffer overflow due to the dangers of gets(). That function is deprecated, meaning it should never be used in newly-written code.
Use fgets() instead:
if(fgets(str1, sizeof str1, stdin) != NULL)
{
/* your code here */
}
Also, of course your entire loop is just strlen() but you knew that, right?
EDIT: Gaah, completely missed the mis-declaration, of course your string should be char str1[25]; and not int.
So, a lot of answers have already told you to use char str1[25]; instead of int str1[25] but nobody explained why. So here goes:
A char has length of one byte (by definition in C standard). But an int uses more bytes (how much depends on architecture and compiler; let's assume 4 here). So if you access index 2 of a char array, you get 1 byte at memory offset 2, but if you access index 2 of an int array, you get 4 bytes at memory offset 8.
When you call gets (which should be avoided since it's unbounded and thus might overflow your array), a string gets copied to the address of str1. That string really is an array of char. So imaging the string would be 123 plus terminating null character. The memory would look like:
Adress: 0 1 2 3
Content: 0x31 0x32 0x33 0x00
When you read str1[0] you get 4 bytes at once, so str1[0] does not return 0x31, you'll get either 0x00333231 (little-endian) or 0x31323300 (big endian).
Accessing str1[1] is already beyond the string.
Now, why do you get a string length of 33? That's actually random and you're "lucky" that the program didn't crash instead. From the start address of str1, you fetch int values until you finally get four 0 bytes in a row. In your memory, there's some random garbage and by pure luck you encounter four 0 bytes after having read 33*4=132 bytes.
So here you can already see that bounds checks are very important: your array is supposed to contain 25 characters. But gets may already write beyond that (solution: use fgets instead). Then you scan without bounds and may thus also access memory well beyond you array and may finally run into non-existing memory regions (which would crash your program). Solution for that: do bounds checks, for example:
// "sizeof(str1)" only works correctly on real arrays here,
// not on "char *" or something!
int l;
for (l = 0; l < sizeof(str1); ++l) {
if (str1[l] == '\0') {
// End of string
break;
}
}
if (l == sizeof(str1)) {
// Did not find a null byte in array!
} else {
// l contains valid string length.
}
I would suggest certain changes to your code.
1) conio.h
This is not a header that is in use. So avoid using it.
2) gets
gets is also not recommended by anyone. So avoid using it. Use fgets() instead
3) int str1[25]
If you want to store a string it should be
char str1[25]
The problem is in the string declaration int str1[25]. It must be char and not int
char str1[25]
void main() //"void" should be "int"
{
int str1[25]; //"int" should be "char"
int i=0;
printf("Enter a string\n");
gets(str1);
while(str1[i]!='\0')
{
i++;
}
printf("String Length %d",i);
getch();
return 0;
}

Resources