I have this C code fully working:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdint.h>
int isAlphaNum(char *str) {
for (int i = 0; str[i] != '\0'; i++)
if (!isalnum(str[i]))
return 0;
return 1;
}
int main() {
char *user_string = "abcdedf0123456789ABCD";
if (isAlphaNum(user_string)) {
printf(" is valid \n");
} else {
printf(" is not valid \n");
}
printf(" \n end \n");
return 0;
}
the following is copied from terminal:
but when I receive input via socket like this:
90a41ae8477a334ba609e06cujdikj#%&%$#$Dkdfsノ,ᅵハ"]モ {ᆳf
or
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒814
the program crashes
at this part:
for (int i = 0; str[i] != '\0'; i++)
if (!isalnum(str[i]))
I used the function by #chqrlie and works:
edited
int isAlphaNum(const char *str) {
//this message is printed , then craches
printf("pass isAlphaNum userinput = %s\n" , str);
while (*str) {
if (!isalnum((unsigned char)*str++))
return 0;
}
return 1;
}
if (isAlphaNum(userinput)) {
printf(" success ;) \n");
}
all ok now
thanks for the help
There is an issue in your code, but it is unlikely to cause the problem on GNU/linux systems, but might on other ones: isalnum(str[i]) has undefined behavior if str[i] has a negative value, which is possible if the string contains 8-bit bytes and the char type is signed by default. isalnum() should only be passed values of the type unsigned char or the special negative value EOF.
The function should be written this way:
#include <ctype.h>
int isAlphaNum(const char *str) {
while (*str) {
if (!isalnum((unsigned char)*str++))
return 0;
}
return 1;
}
Your remark about receiving input via socket prompts me to suspect that you are not null terminating the string received via a socket. This could cause isAlphaNum() to read beyond the end of the array and cause a segmentation fault if there is no null byte until the end of the memory mapped area (which used to be called a segment in ancient Multics systems).
Related
So I'm learning the char arrays in C. I wrote a little program which works with functions and reads input from terminal and on EOF will printf the char array.
If I enter, for example: hello my name is and press enter, I receive this output: hello my z Ͳ
I don't understand where the z Ͳ comes from. Can someone explain it to me?
#include <stdio.h>
const int MAXLENGTH = 10;
int getLine(char[], int);
int main(void) {
char inputString[MAXLENGTH];
getLine(inputString, MAXLENGTH);
printf("%s", inputString);
return 0;
}
// Functions:
int getLine(char destArray[], int length) {
int returnLength;
int input;
for (int i = 0; i < length - 1; i++) {
if ((input = getchar()) != EOF) {
destArray[i] = input;
returnLength = i;
}
}
return returnLength;
}
There are multiple problems in your code:
you do not store a null terminator at the end of the destination array in getLine().
you should stop read from stdin when you get a newline ('\n') or an EOF value.
Here is a modified version:
#include <stdio.h>
const int MAXLENGTH = 10;
int getLine(char[], int);
int main(void) {
char inputString[MAXLENGTH];
getLine(inputString, MAXLENGTH);
printf("%s\n", inputString);
return 0;
}
// Functions:
int getLine(char destArray[], int length) {
int i, c;
for (i = 0; i < length - 1; i++) {
c = getchar();
if (c == EOF || c == '\n')
break;
destArray[i] = c;
}
destArray[i] = '\0';
return i;
}
Running this program will show that hello my name is does not fit in the destination array as the program's output will be hello my
In your program, you were not storing anything beyond the end of the buffer, because you correctly test i < length - 1, but printf did read beyond the 9-th byte set by getLine() and printed whatever contents was in memory at those addresses until it finds a null byte, which is undefined behavior. The weird output is a benign side effect of undefined behavior, the program could have crashed too. The bytes in the memory probably correspond to values stored in the stack for the main() function local frame and return address. Different compilers, different platforms or even different invocations of the same program could produce different output (the latter may seem unlikely, but would happen on OS/X because of stack randomisation).
I'm building a program for reversing a string in visual studio, and while I run the code and enter a word I want to reverse, the program crashes.
#include <stdio.h>
#include <conio.h>
#include <string.h>
main(void) {
char r[256];
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(" %s", r, sizeof(r));
d = strlen(r);
for (i=d;i!=0;i--) {
printf("%s",i);
}
return 0;
}
Please note that I tried your program on Linux, so no MS Visual C++ and more specifically no conio.h and gets_s.
There are multiple problems with your program:
Your call to gets_s is incorrect, according to this and this, gets_s is defined as:
char *gets_s(
char *buffer,
size_t sizeInCharacters
);
You are calling it with illegal arguments. Instead of gets_s(" %s", r, sizeof(r)); you need to call it like this:
gets_s(r, 256);
the first parameter is pointer to the string buffer where the gets_s function will store the line from input and the second is the size of the buffer, note that in char r[256] you can store 255 characters and terminating zero (\0).
Your for loop is incorrect instead of for (i=d;i!=0;i--) { you need to do it like this:
for (i=d-1;i>=0;i--) {
now the loop starts from last character instead of \0 and ends when the i < 0 ie. the last print will be when i=0.
And your final mistake is that you are using printf incorrectly instead of printf("%s",i); you need to do:
printf("%c",r[i]);
because you are printing characters: "%c" is for char output and r[i] is i-th character from string r (don't forget that we count from 0).
So, in total this is how the program should look like:
#include <stdio.h>
#include <conio.h> // does not exist on GCC (Linux)
#include <string.h>
main(void) {
char r[256]; // 255 characters + \0
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(r, 256); // store at most 255 characters + \0
// does not work on GCC (Linux) even with -std=C11
d = strlen(r);
// start from last character and include first
for (i=d-1;i>=0;i--) {
// %c - character, r[i] gets the i-th character from string r
printf("%c",r[i]);
}
return 0;
}
void rev(char *s)
{
char *start, *end;
end = start + strlen(s) - 1;
for (start = s; end > start; ++start, --end) {
char tmp;
tmp = *start;
*start = *end;
*end = tmp;
}
}
Use the fgets function, and also put the reversing code in its own function, like I did. So the final code is
int main()
{
char line[80];
fgets(line, 80, stdin);
/* don't allow empty string */
if (*line == '\0') {
fprintf(stderr, "Empty string is not a string\n");
return 1;
}
/* remove the \n placed by fgets */
remnl(line);
rev(line);
printf("%s\n", line);
return 0;
}
void remnl(char *s) { s[strlen(s) - 1] = 0; }
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main(void) {
char r[256];
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(r, sizeof(r));
d = strlen(r) - 1;
for (i = d; i >= 0; i--) {
printf("%c", r[i]);
}
_getch();
return 0;
}
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 256
int main(int argc, const char * argv[]) {
char testo[N];
int i;
printf("PER TERMINARE L'INSERIMENTO PREMERE CTRL+Z oppure CTRL+D \n");
for(i=0;i<N;i++)
{
scanf("%c",&testo[i]);
/* if(testo[i]=='h' && testo[i-1]=='c')
{
i--;
testo[i]='k';
}
if(testo[i]==testo[i-1])
{
i--;
} */
if(testo[i]==EOF)
{
break;
}
}
puts(testo);
return 0;
}
When the code in /* ... */ is compiled, I can't stop the insert of text with EOF, but when the code is built and run as shown here, the EOF works.
Does anyone have any idea what the problem is?
You're testing for EOF incorrectly. With scanf(), you need to look at the return value. In fact, with almost all input functions, you need to test, if not capture and test, the return value.
Superficially, you need:
for (i = 0; i < N; i++)
{
if (scanf("%c", &testo[i]) == EOF)
break;
…
}
However, in general, you should check that scanf() made as many successful conversions as you requested, so it is better to write:
for (i = 0; i < N; i++)
{
if (scanf("%c", &testo[i]) != 1)
break;
…
}
In this example, it really won't matter. If you were reading numeric data, though, it would matter. The user might type Z instead of a number, and scanf() would return 0, not EOF.
To detect EOF, check the result of scanf()
if scanf("%c",&testo[i]) == EOF) break;
Note: testo[] may not be null character terminated. To print as a string, insure it is.
char testo[N];
int i;
// for(i=0;i<N;i++) {
for(i=0;i<(N-1);i++) {
if (scanf("%c",&testo[i]) == EOF) break;
}
testo[i] = '\0'; // add
puts(testo);
To stop at end of file, check the return value from scanf:
scanf returns the number of inputs correctly parsed. In your case, %c reads a byte from the stream correctly as long as end of file has not been reached. if (scanf("%c",&testo[i]) != 1) break; will do.
Yet using scanf to read one byte at a time from the input stream is overkill. The idiomatic way to do this in C is using the getchar() or the getc() function. The return value must be stored in an int variable and has special value EOF upon end of file.
You should also make the array 1 byte longer and store a null byte at the end to make it a C string, as expected by puts.
Here is a modified version of your program:
int main(int argc, const char *argv[]) {
char testo[N+1];
int i;
printf("PER TERMINARE L'INSERIMENTO PREMERE CTRL+Z oppure CTRL+D\n");
for (i = 0; i < N; i++) {
int c = getchar();
if (c == EOF)
break;
testo[i] = c;
/* ... further processing ... */
}
testo[i] = '\0';
puts(testo);
return 0;
}
Below is my piece of code, I don't understand why it always gives me the segmentation fault:
#include <stdio.h>
void reverse(void);
int main ()
{
printf("enter the text");
printf("\n");
reverse();
printf("\n");
return(0);
}
void reverse(void)
{
char c;
if((c=getchar()) != '\n')
{
reverse();
}
putchar(c);
}
In my opinion I have done everything correctly, what is the mistake?
The code works fine as long as you enter a newline. Perhaps you are terminating your input with EOF (usually bound to Ctrl+D) without feeding it a newline before, and in that case, the code will never see a newline and there will be a stack overflow due to infinite recursion.
So, you should check that getchar() doesn't return EOF. Also, getchar() returns int, not char - this is important for portability and to make sure that comparison with EOF works as expected.
Here's the code after addressing these issues:
#include <stdio.h>
void reverse(void);
int main (void) {
printf("enter the text\n");
reverse();
printf("\n");
return 0;
}
void reverse(void) {
int c;
if ((c=getchar()) != '\n' && c != EOF) {
reverse();
}
if (c != EOF) {
putchar(c);
}
}
Your program compiled and ran fine on my setup: latest stable gcc on Ubuntu 14.04.2 LTS 64-bit.
Here is another version using a different approach (namely the fgets function). See if it works for you:
#include <stdio.h>
#include <string.h>
void reverse_str( char * );
int main()
{
char input[1024];
printf("Enter text: ");
fgets(input, sizeof(input), stdin);
reverse_str(input);
printf("Reversed string: %s\n", input);
return 0;
}
void reverse_str(char *to_reverse)
{
char temp[1024];
int count = strlen(to_reverse) - 1; //Exclude newline introduced with fgets
int i=0;
for( i=count; i>=0; i-- ){
temp[i] = to_reverse[count - i - 1]; //Subtract 1 to not include the new line introduced by fgets
}
temp[count+1] = '\0';
strcpy(to_reverse, temp);
}
Your code seems to failing because of the nasty characters of getchar()..In most of the system it should work but I think your compiler is trying to access the memory saved beyond the array & hence generating segmentation fault...Can you please make sure if you give '\0' in place of '\n', it is working or not..I think the problem is that your machine is not able to detect the '\n' given from your keyboard & hence keep on going into recursion mode & stack is overflown before the recursion ends & when stack is overflown, it is trying to access unauthorised memory & hence segmentation fault occurs
Try this
#include <stdio.h>
#include <string.h>
char str[] = "Hello World";
size_t length;
int count = 0;
void reverse(char* a, char* b){
// static int count = 0;
char temp;
if (count < length/2){
count++;
reverse(str + count, str + (length - 1) - count);
}
temp = *a;
*a = *b;
*b = temp;
}
int main(){
length = strlen(str);
reverse(str, str + length - 1);
printf("%s", str);
return 0;
}
I don't understand why the program below returns "z#" as string. But when I put a printf("%s \n",""); before that, then it returns "11110111" (as aspected).
Can anybody help me to understand this behaviour?
Many thanks in advance!
Please find my whole program posted below:
#include <stdio.h>
char * bin2str(unsigned char bin) {
char str[] = "00000000";
int i;
for (i=7; i>=0; i--) {
if ((bin%2)==0) {
str[i] = '0';
} else {
str[i] = '1';
}
bin = bin >> 1;
}
return ((char *) str);
}
int main() {
unsigned char testChar;
testChar |= 0b11110111;
printf("Let us test binary to string: \n\n \n");
//printf("%s \n","");
printf("%s \n", bin2str(testChar)); //now it returns rubbish, but when the previous line is uncommented it turns out to be working correctly. Why?
return 0;
}
You are returning the local variable str from the function bin2str which is undefined behaviour. Instead you could copy it using strdup() (or its equivalent using malloc() + strcpy()).
char *str = strdup("00000000");
and return it.
Don't forget to free() it!
You are generating a string as a local variable inside bin2str(). That string will be located in stack space while bin2str() is executing. As soon as the function returns, the stack space is no longer valid, and the memory pointed by str will contains whether the program puts in the stack between the return from the call to bin2str() and the call to printf() where you intend to print the contents of str.
Alternatives:
Declare str as static. This way, str won't be placed in stack space and its contents will be available even after the function ends. Beware! as this solution is not thread safe.
Change your prototype so it accepts a second argument, which will be the address of a string that the caller will have to provide, to which bin2str() will write the binary representation of the number.
Thanks you all for your feedback. Wow, that was fast!
It was my first post.
I made the changes. Please find the correct functioning program below (without compile warnings):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * bin2str(unsigned char bin) {
char *str = strdup("00000000");
int i;
for (i=7; i>=0; i--) {
if ((bin%2)==0) {
str[i] = '0';
} else {
str[i] = '1';
}
bin = bin >> 1;
}
return ((char *) str);
free(str);
}
int main() {
unsigned char testChar;
testChar |= 0b11110111;
printf("Let us test binary to string: \n\n \n");
printf("%s \n", bin2str(testChar));
return 0;
}