String comparison function - c

I am new to C and am trying to figure out and learn why my code isn't working. I understand that in C a string is basically an Array of each character. So I have been trying to search through the array to find the letter a and then print something if it is found. But my program keeps crashing every time I try to run it.
Here is my code:
#include <stdio.h>
void Display(char ch[]);
int main() {
char c[50];
printf("Enter String: ");
gets(c);
Display(c);
return 0;
}
void Display(char ch[]) {
int i;
for (i = 0; i < (sizeof(ch)); i++) {
if (strcmp(ch[i],"a") == 0) {
printf( "Yes");
}
}
}
When I run my program I enter a random string for example "fdas" and press enter. Then it crashes =\
Please remember I am new to C. I am a Java programmer if that helps with any explanations.

This is wrong
if(strcmp(ch[i],"a") == 0)
it should be
if (ch[i] == 'a')
and also, sizeof(ch) is not giving you the length of the string, for that you need strlen(), your Display() function should look like this to work
void Display(char *ch) {
size_t i;
size_t length;
if (ch == NULL)
return;
length = strlen(ch);
for (i = 0 ; i < length ; i++) {
if (ch[i] == 'a') {
printf( "Yes");
}
}
}
also, using gets() is unsafe, and deprecated, usefgets()
fgets(c, sizeof(c), stdin);
is better than gets(c) because it will prevent buffer overflow, note that I've used the sizeof operator in this case, because c is an array of char and the sizeof operator will give it's size in bytes, and since 1 char == 1 byte then it works.
In the case of the Display() function, it's not the same because there the sizeof operator will give the size of the type of ch, and since what you really need is the count of characters that ch points to, so you must use strlen() or compute the length yourself.

Related

It's not printing the new array. What could be the reason?

#include <stdio.h>
char q[50];
int doo(int p, int n, char* s) {
int i = 0, j = 0;
while (s[i] != '\0') {
if ((i < p) && (i > (p + n))) {
q[j] = s[i];
++j;
}
i++;
}
puts(p);
}
int main() {
char s[50];
int n, p;
printf("<--program by gautam-->\n");
printf("enter the string-->");
gets(s);
printf("\nenter the numbers of character to be deleted and position-->");
scanf("%d%d", &n, &p);
--p;
doo(p, n, s);
return 0;
}
The task is to delete certain elements of a string by asking the user the position and number of elements to delete. I'm trying to copy all elements except those whose position is provided by user, but I'm getting no output at all.
The fundamental error in your code is that you are using the && operator in the test inside your while loop, whereas you should be using the || operator: if either of the conditions is true, then add the character to the output string.
Also, your doo function is declared as returning an int but it doesn't return anything: I fixed this in the code below by returning j (the count of characters copied) but, as you never use that, you may want to redeclare the function as void, instead.
You are also attempting to print p with the puts function, where you most likely want to print q (I can put this one down to a typo).
Lastly: Never use the gets function! Why is the gets function so dangerous that it should not be used? Use fgets(), instead - it's much safer, as it will never read in more characters than you tell it to, so the buffer won't overflow (if you specify the correct size).
Here's a 'fixed' version of your code, with comments added where I've made changes:
#include <stdio.h>
char q[50];
int doo(int p, int n, char* s)
{
int i = 0, j = 0;
while (s[i] != '\0') {
if ((i < p) || (i > (p + n))) { // Need OR not AND here
q[j] = s[i];
++j;
}
i++;
}
q[j] = '\0'; // Add nul terminator (don't need if only calling once, but best to have it anyway)
puts(q); // Should be printing "q" (result string) NOT "p" (position).
return j; // MUST return something - here, the count of characters
}
int main()
{
char s[50];
int n, p;
printf("<--program by gautam-->\n");
printf("enter the string-->");
fgets(s, 50, stdin); // NEVER use gets - it's been removed from the language!
printf("\nenter the numbers of character to be deleted and position-->");
scanf("%d%d", &n, &p);
--p;
doo(p, n, s);
return 0;
}

C programming: strlcpy with len = 0 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm just learning about programming using the C language.
Today, I'm trying to code my own strlcpy function and I am facing a problem.
To test my function I compare the results with the "official" function's ones. Everything works fine except... When I put 0 as the len arg.
The strcpy function seems to put a garbage character in the destination string and I really don't understand why.
Here is the function's prototype:
size_t strlcpy(char * restrict dst, const char * restrict src, size_t dstsize);
Thanks for your help!
Ok. I wanted to make a lot of tests, this is the reason why I'm calling the function inside of a loop.
Here is a part of my main function, testing the function:
do
{
/* Ask for first string */
printf("\nGive me a string (0 to stop): ");
gets(str);
/* Ask for a number */
printf("Now, give me a number please: ");
scanf("%d", &i);
while (getchar() != '\n');
/* I test with the "official function */
j = strlcpy(str2, str, i);
printf("Here is the expected result: %s\n", str2);
printf("Num returned: %d\n", j);
/* Now I test using my function */
j = ft_strlcpy(str3, str, i);
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}while (str[0] != '0');
And here is the function I've coded:
unsigned int ft_strlcpy(char *dest, char *src, unsigned int size)
{
unsigned int cpt;
unsigned int i;
cpt = 0;
i = 0;
while (src[cpt] != '\0')
cpt++;
if (size == 0)
return (0);
while (i < cpt && i < (size - 1))
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (cpt);
}
In the function I'm not supposed to call any function from the standard library. My main is just here for testing.
The function prototype is given by my teacher, this is the reason why I don't respect the original one.
Sorry fort the time I needed to put my code here and thank you for your help.
could you explain me where the "garbage character" comes from? What does the function do to find this character and to put it in the string? Even if it is not supposed to be called with a 0 len value.
The manual does not say that strlcpy is not supposed to be called with a 0 len value, it only says that it isn't NUL-terminating the result if dstsize is 0, i. e. it copies no characters at all to dst.
Your impression that it would put a "garbage character" into the destination string most probably results from dst being uninitialized from the start, and you looking at the unchanged, uninitialized dst.
First of all, I suppose you mistype in "...strlen function seems to put a garbage..." (strlcpy should be instead of strlen, because strlen put nothing to string - size_t strlen(const char *s);).
So you have a question about strlcpy.
As referencess said about the third argument of strlcpy (as well as strncpy) determies number of characters to be copied from src to dst. So, in case of 0-size no data should be copied. Read documentation carefully - prototype is:
strlcpy(char *dst, const char *src, size_t size);
and explanation for size has words:
as long as size is larger than 0
There are several issues in your program.
First of all don't use gets(). It's not safe and moreover it has been obsoleted. Check this.
Instead use fgets(). Check this.
In this statement
printf("\nGive me a string (0 to stop): ");
0 to stop will actually not stop anything and execute all the statements below it until while loop checks the condition. May you want a put if condition, like this:
if (str[0] != '0') {
.....
.....
}
}while (str[0] != '0');
In this statement
printf("Now, give me a number please: ");
scanf("%d", &i);
....
....
j = ft_strlcpy(str3, str, i);
You are passing this number as the destination size to your ft_strlcpy() function. Assume your source string contains "123456789" string and destination string size is 5 and user has given number input as 100. In function ft_strlcpy(), for the given input
//cpt variable value would be 9
//size variable value would be 100
//initial value of i is 0
while (i < 9 && i < (100 - 1))
{
dest[i] = src[i]; //buffer overflow!!!!, this statement will execute 9 times and dest buffer size is 5
i++;
}
So, instead of taking the number of characters to be copy as input from user, you should give size of the destination buffer. Like this
j = ft_strlcpy(str3, str, sizeof(str3));
From strlcpy
strlcpy() copies up to dstsize - 1 characters from the string src to dst,
NUL-terminating the result if dstsize is not 0.
That means if destination buffer size is 0, no copy is performed.
Check this also.
Putting these all together, you can do:
#include <stdio.h>
#include <string.h>
unsigned int ft_strlcpy(char *dest, const char *src, unsigned int size) {
unsigned int i = 0, j = 0;
while (src[i] != '\0') {
if (size && (i < (size - 1))) {
dest[i] = src[i];
j++;
}
i++;
}
dest[j] = '\0';
return (i);
}
int main() {
char str[100], str3[100];
unsigned int j;
do {
/* Ask for first string */
printf("\nEnter a string (press only enter key to stop): ");
if (fgets(str, sizeof(str), stdin) == NULL) {
fprintf (stderr, "Failed to read input");
break;
}
/* If input is bigger than the size of buffer, discard the rest of input characters */
if (strchr(str, '\n') == NULL) {
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
else {
/* Remove the trailing newline character */
str[strcspn(str, "\n")] = 0;
}
if (str[0] != '\0') {
j = ft_strlcpy(str3, str, sizeof(str3));
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}
}while (str[0] != '\0');
return 0;
}

Why is it showing random numbers? C program to read string letters

So I have to create a program that reads the user input and shows how many times each letter appears in that string, and also how many non-letters but my code for alphabets is showing random numbers..
#include <stdio.h>
#include <string.h>
#define SIZE 100
void readInput (char string[]);
void Calc(char string[], int letters[]);
void
readInput (char string[])
{
printf ("Enter a String:\n");
fgets (string, SIZE, stdin);
string[strlen (string) - 1] = '\0';
}
void
Calc(char string[], int letters[])
{
int c = 0, x;
while (string[c] != '\0')
{
if (string[c] >= 'a' && string[c] <= 'z')
{
x = string[c] - 'a';
letters[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
printf ("%c occurs %d times in the entered string.\n", c + 'a', letters[c]);
}
int
main ()
{
char string[SIZE];
int letters[26];
readInput (string);
Calc(string, letters);
return 0;
}
This is the output
I'm new to strings I've googled examples but can't seem to find whats wrong with my code and no idea how I will include the non-letters part.
The contents of letters are not initialised. Formally the behaviour of your program is indeterminate.
Sort that by writing int letters[26] = {0}; Doing that sets all elements to zero, which is what you want in this case.
letters[] is uniinitialized.
Solution int letters[26]={0}.
You are reading an uninitialized value which is indeterminate. And the results doesn't conform to as you expect it to be.
Here you want to initialize the elements with 0 denoting that you haven't seen any charcaters yet. (automatic storage duration).
A better way to overwrite the '\n' would be
string[strcspn(string, "\n")] = 0;
you should initialize letters with all 0 values

Scanf for reading string and int array in brackets

I've been trying to come up with solution for reading input which contains string and then brackets with array of numbers (I don't know how many numbers will be inputed.
Input could look like:
sacrifice (1, 2, 4, 2)
I am wondering if it is possible to achieve with scanf. I've been looking for different functions such as getline, sscanf, fgets and so on. But I couldn't come up with solution.
My code looks like this:
scanf("%[^(]", command);
while ( ( c = getchar() ) != ')' )
{
scanf("%d", weights[pos]);
pos++;
}
Which should read string until the bracket is found and then I tried to load the numbers in array as long as it doesn't reach the ')'. Yet it doesn't seem to work.
Is scanf viable to achieve this? Could anyone point me in better direction if not please?
I think it would be simpler to read the complete line from stdin and then parse it by hand using strtok or strcspn. Something like below could be done.
Disclaimer: This is just some sample code and doesn't handle all possible inputs and will crash with invalid input, it is just to give you an idea about how to do it. If you want to go this way, you would have to handle various error conditions, such as:
checking return value of malloc/getline/realloc
instead of atoi using a better function like strtol (which allows error checking),
handling white spaces in the input and
handling input which does not contain any parenthesis
Those are some of the many things which you would have to think about.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int *parse_numbers(char *numstr, size_t *size)
{
char *p;
char *s = numstr;
char *last;
size_t array_size = 10;
int *numbers = malloc(sizeof(int) * array_size);
size_t offset = 0;
for (p = strtok_r(s, ",", &last); p; p = strtok_r(NULL, ",", &last)) {
if (offset == array_size) {
array_size *= 2;
numbers = realloc(numbers, sizeof(int) * array_size);
//TODO do error check
}
numbers[offset++] = atoi(p); //strtol would be a better choice
}
*size = offset;
return numbers;
}
int main()
{
char *s = NULL;
char *p;
char *last;
int i = 0;
int *numbers;
size_t size;
size_t linesize = 0;
getline(&s, &linesize, stdin);
for (p = strtok_r(s, "(", &last); p; p = strtok_r(NULL, "(", &last)) {
if (i++ == 0) {
//This is the part of the string before '('
cmd = p;
} else {
// This is the part of the string after '('
numbers = parse_numbers(p, &size);
}
}
for (i = 0; i < size; i++) {
printf("%d\n", numbers[i]);
}
free(numbers);
free(s);
return 0;
}
Separate input from parsing. Far easier to handle the various issues of command processing. Concerning "don't know how many numbers will be inputed", IMO, a reasonable upper bound should be established. Else code is susceptible to overwhelming memory resources due to user input - a hacker exploit.
char command[1000];
while (fgets(command, sizeof command, stdin)) {
Now process the command using sscanf(), strtok() or your own code. The best method depends on maybe things not posted by OP, especially error handling.
int cmd_start;
int cmd_end;
int n = 0;
// sacrifice (1, 2, 4, 2, ...)
// +----------------- skip optional white space
// |+---------------- record scan position
// || +-------------- scan, but not save, lower case letters
// || | +------- record scan position
// || | | +----- skip optional white space
// || | | |+---- scan (
// || | | ||+--- skip optional white space
// || | | |||+-- record scan position
sscanf(command, " %n%*[a-z]%n ( %n", &cmd_start, &cmd_end, &n);
if (n == 0) {
printf("Invalid command '%s'\n", command);
continue;
}
int x[sizeof command / 2];
int x_count = 0;
char *p = &command[n]; // pick up where previous scan ended.
char sep[2] = {0};
while (sscanf(p, "%d %1[,)] %n", &x[x_count], sep, &n) == 2) {
x_count++;
p += n;
if (sep[0] == ')') break;
}
if (*p || sep[0] != ')') {
printf("Invalid separator '%s'\n", command);
continue;
}
// Use command
command[cmd_end] = '\0';
Process_Command(&command[cmd_start], x, x_count);
}
scanf("%d", weights[pos]); --> scanf("%d", &weights[pos]); – BLUEPIXY
That's indeed adequate to make the code work, provided a sufficiently dimensioned weights array.

C program, Reversing an array

I am writing C program that reads input from the standard input a line of characters.Then output the line of characters in reverse order.
it doesn't print reversed array, instead it prints the regular array.
Can anyone help me?
What am I doing wrong?
main()
{
int count;
int MAX_SIZE = 20;
char c;
char arr[MAX_SIZE];
char revArr[MAX_SIZE];
while(c != EOF)
{
count = 0;
c = getchar();
arr[count++] = c;
getReverse(revArr, arr);
printf("%s", revArr);
if (c == '\n')
{
printf("\n");
count = 0;
}
}
}
void getReverse(char dest[], char src[])
{
int i, j, n = sizeof(src);
for (i = n - 1, j = 0; i >= 0; i--)
{
j = 0;
dest[j] = src[i];
j++;
}
}
You have quite a few problems in there. The first is that there is no prototype in scope for getReverse() when you use it in main(). You should either provide a prototype or just move getReverse() to above main() so that main() knows about it.
The second is the fact that you're trying to reverse the string after every character being entered, and that your input method is not quite right (it checks an indeterminate c before ever getting a character). It would be better as something like this:
count = 0;
c = getchar();
while (c != EOF) {
arr[count++] = c;
c = getchar();
}
arr[count] = '\0';
That will get you a proper C string albeit one with a newline on the end, and even possibly a multi-line string, which doesn't match your specs ("reads input from the standard input a line of characters"). If you want a newline or file-end to terminate input, you can use this instead:
count = 0;
c = getchar();
while ((c != '\n') && (c != EOF)) {
arr[count++] = c;
c = getchar();
}
arr[count] = '\0';
And, on top of that, c should actually be an int, not a char, because it has to be able to store every possible character plus the EOF marker.
Your getReverse() function also has problems, mainly due to the fact it's not putting an end-string marker at the end of the array but also because it uses the wrong size (sizeof rather than strlen) and because it appears to re-initialise j every time through the loop. In any case, it can be greatly simplified:
void getReverse (char *dest, char *src) {
int i = strlen(src) - 1, j = 0;
while (i >= 0) {
dest[j] = src[i];
j++;
i--;
}
dest[j] = '\0';
}
or, once you're a proficient coder:
void getReverse (char *dest, char *src) {
int i = strlen(src) - 1, j = 0;
while (i >= 0)
dest[j++] = src[i--];
dest[j] = '\0';
}
If you need a main program which gives you reversed characters for each line, you can do that with something like this:
int main (void) {
int count;
int MAX_SIZE = 20;
int c;
char arr[MAX_SIZE];
char revArr[MAX_SIZE];
c = getchar();
count = 0;
while(c != EOF) {
if (c != '\n') {
arr[count++] = c;
c = getchar();
continue;
}
arr[count] = '\0';
getReverse(revArr, arr);
printf("'%s' => '%s'\n", arr, revArr);
count = 0;
c = getchar();
}
return 0;
}
which, on a sample run, shows:
pax> ./testprog
hello
'hello' => 'olleh'
goodbye
'goodbye' => 'eybdoog'
a man a plan a canal panama
'a man a plan a canal panama' => 'amanap lanac a nalp a nam a'
Your 'count' variable goes to 0 every time the while loop runs.
Count is initialised to 0 everytime the loop is entered
you are sending the array with each character for reversal which is not a very bright thing to do but won't create problems. Rather, first store all the characters in the array and send it once to the getreverse function after the array is complete.
sizeof(src) will not give the number of characters. How about you send i after the loop was terminated in main as a parameter too. Ofcourse there are many ways and various function but since it seems like you are in the initial stages, you can try up strlen and other such functions.
you have initialised j to 0 in the for loop but again, specifying it INSIDE the loop will initialise the value everytime its run from the top hence j ends up not incrmenting. So remore the j=0 and i=0 from INSIDE the loop since you only need to get it initialised once.
check this out
#include <stdio.h>
#include <ctype.h>
void getReverse(char dest[], char src[], int count);
int main()
{
// *always* initialize variables
int count = 0;
const int MaxLen = 20; // max length string, leave upper case names for MACROS
const int MaxSize = MaxLen + 1; // add one for ending \0
int c = '\0';
char arr[MaxSize] = {0};
char revArr[MaxSize] = {0};
// first collect characters to be reversed
// note that input is buffered so user could enter more than MAX_SIZE
do
{
c = fgetc(stdin);
if ( c != EOF && (isalpha(c) || isdigit(c))) // only consider "proper" characters
{
arr[count++] = (char)c;
}
}
while(c != EOF && c != '\n' && count < MaxLen); // EOF or Newline or MaxLen
getReverse( revArr, arr, count );
printf("%s\n", revArr);
return 0;
}
void getReverse(char dest[], char src[], int count)
{
int i = count - 1;
int j = 0;
while ( i > -1 )
{
dest[j++] = src[i--];
}
}
Dealing with strings is a rich source of bugs in C, because even simple operations like copying and modifying require thinking about issues of allocation and storage. This problem though can be simplified considerably by thinking of the input and output not as strings but as streams of characters, and relying on recursion and local storage to handle all allocation.
The following is a complete program that will read one line of standard input and print its reverse to standard output, with the length of the input limited only by the growth of the stack:
int florb (int c) { return c == '\n' ? c : putchar(florb(getchar())), c; }
main() { florb('-'); }
..or check this
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
char *my_rev(const char *source);
int main(void)
{
char *stringA;
stringA = malloc(MAX); /* memory allocation for 100 characters */
if(stringA == NULL) /* if malloc returns NULL error msg is printed and program exits */
{
fprintf(stdout, "Out of memory error\n");
exit(1);
}
else
{
fprintf(stdout, "Type a string:\n");
fgets(stringA, MAX, stdin);
my_rev(stringA);
}
return 0;
}
char *my_rev(const char *source) /* const makes sure that function does not modify the value pointed to by source pointer */
{
int len = 0; /* first function calculates the length of the string */
while(*source != '\n') /* fgets preserves terminating newline, that's why \n is used instead of \0 */
{
len++;
*source++;
}
len--; /* length calculation includes newline, so length is subtracted by one */
*source--; /* pointer moved to point to last character instead of \n */
int b;
for(b = len; b >= 0; b--) /* for loop prints string in reverse order */
{
fprintf(stdout, "%c", *source);
len--;
*source--;
}
return;
}
Output looks like this:
Type a string:
writing about C programming
gnimmargorp C tuoba gnitirw

Resources