Problem Statement
Today is Newton School's first class of this year. Nutan, a student at
Newton School, has received his first assignment. He will be given a
string as input. His task is to print "Gravity'' if the input is
"Apple''; otherwise, he will have to print "Space''.
Can you help Nutan in solving his first assignment? Note that the
quotation marks are just for clarity. They are not part of the input
string, and should not be a part of your output string. Input The
input consists of a single line that contains a string S (1 ≤ length
of S ≤ 10). The string only consists of lowercase and uppercase
letters. Output Print "Gravity'' or "Space'' according to the input.
What I am trying to do:
Basically, I am taking a user-defined string and trying to compare it with the hard input string i.e "Apple". If both the string matches then it will print "Gravity" or else it will print "Space"
#include <stdio.h> // header file for Standard Input Output
#include <stdlib.h> // header file for Standard Library
#include <string.h> // for strcmp() function
int main() {
char str1[10]="Apple";
char str2[20];
int value;
printf("Enter the input ");
scanf("%s", &str2[20]);
value = strcmp(str1, str2);
if(value==0)
printf("Gravity");
else
printf("Space");
return 0;
}
scanf("%s", &str2[20]);
may invoke undefined behavior by out-of-range access. You should:
Pass the pointer to the first element of the array, not one to the next element of the last element. (most) arrays in expressions are automatically converted to pointes to their first elements.
Specify the maximum length to read to avoid buffer overrun.
Check if reading succeeded.
The line should be:
if (scanf("%19s", str2) != 1) {
puts("read error");
return 1;
}
Some improvements:
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
always check whether scanf() input was successful or not
Use const char * instead of char str1[10]
There's no need for int value;
SYNTAX ERROR: &str2[20]
There's no need for passing the address of str2 READ MORE
Initialize str2 with zeroes
Add 1 more space in your str2 for NULL ('\0') terminating character
Final Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *str1 = "Apple";
char str2[21] = {};
printf("Enter the input ");
if(scanf("%20s", str2) != 1)
{
fprintf(stderr, "bad input\n");
return EXIT_FAILURE;
}
if(strcmp(str1, str2) == 0)
printf("Gravity");
else
printf("Space");
return EXIT_SUCCESS;
}
You are entering a string starting from the memory address after the last element of the array str2
scanf("%s", &str2[20]);
and then trying to compare the character array str1 with the non-initialized array str2
value = strcmp(str1, str2);
Change the call of scanf like
scanf("%19s", str2);
And the program will be safer if at least the array str2 will be initially initialized
char str2[20] = "";
Also as the array str1 is not changed then instead of the array you could declare a pointer to the string literal like
const char *str1 = "Apple";
And instead of the calls of printf
printf("Gravity");
//..
printf("Space");
it is better to use calls of puts
puts("Gravity");
//..
puts("Space");
Pay attention to that neither declaration from the header <stdlib.h> is used in your program. So you may remove this include directive
#include <stdlib.h> // header file for Standard Library
Related
Iterating through a fixed-length string is easy, but when a variable-length string is used, the iteration fails after 0-th index.
For example, in the code below (printing characters of a string p one-by-one), using p[] doesn't work, while p[some integer] work (but we don't always know what that some integer is).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
setbuf(stdout, NULL);
// variable p to store string
// if you change the line to let's say char p[20]=""; it will work
char p[]="";
printf("Enter a string: ");
scanf("%s", p);
printf("You entered: %s\n", p);
printf("String length: %d\n", strlen(p));
printf("Printing each character of the string:\n");
int i=0;
while (p[i] != '\0')
{
printf("p[%d] is %c\n", i, p[i]);
i++;
}
return 0;
}
When an array is not given an initial size, it is made exactly large enough to hold what it is initialized with. In this case, you initialize a char array with the empty string "". This string constant consists of a single null byte, so p is an array of size 1.
Then when you attempt to read a string into it you write past the end of the array, invoking undefined behavior.
If we omit the array dimension, compiler computes it for us based on the size of initialiser.
In this statement:
char p[]="";
the initialiser is an empty string literal (string literal with only a '\0' character). So, the size of char array p will be 1.
Accessing an array beyond its size is undefined behavior. An undefined behavior includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.
Here's my code and I can't seem to figure out how to make the function with only the array as argument.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char strArray[30] = "Print this string backward.";
puts("");
stringReverse(strArray);
return(0);
}
void stringReverse(char strArray[])
{
if(strArray != "\n") {
stringReverse(&strArray)
printf("%s", strArray)
}
}
A few observations and criticisms:
The math.h and stdlib.h header files are not needed for the posted code. While char strArray[30] is large enough to hold the input string, it is better to use empty brackets in a string initializer unless you need a specific size that is larger than the initial string. This is less error-prone, and just easier, since there is no need to count characters, and no need to remember to include space for the null-terminator. You probably want to move the puts(""); to after the call to stringReverse(), since this function does not print a newline character. It usually seems better to use putchar('\n'); for something like this; putchar() is designed to print only one character, and so is the right tool for the job.
It seems that with the statement if (strArray != "\n") {} the goal is to check if the first character is a newline, but there are a few problems with this. First, "\n" is a string, not a character; next, strArray is a pointer to the first character of the array strArray[], not the first character itself. There is no '\n' character in the input string, so even if this condition were correctly written, it would always be true, and this code would enter an infinite recursion. Finally, the argument passed to stringReverse() is never changed, so there is no way for the recursion to end. For recursion to succeed, a base case must be converged upon.
A solution is to compare the first character of the array with '\0'. If the first character is not the null-terminator, the stringReverse() function is called again, this time with the value strArray + 1. The program will continue recursively calling stringReverse() until an empty string is passed in, at which point the final call to stringReverse() returns to its caller (the previous call to stringReverse()), where the last character of the string is printed, before returning to its caller,.... Each of the stringReverse() frames is returned to, in the reversed order in which they were called, and each of these frames prints a character of the string, until finally the first frame is reached, and the first character is printed, before returning to main().
Note that in a function call, and in fact most expressions, arrays decay to pointers to their first elements. So, in stringReverse() strArray is a pointer to char that points to the first element of the array provided as an argument by the caller. Also note that in a function declaration such as void stringReverse(char strArray[]) array types are adjusted to appropriate pointer types, so this declaration is equivalent to void stringReverse(char *strArray).
#include <stdio.h>
void stringReverse(char strArray[]);
int main(void)
{
char strArray[] = "Print this string backwards.";
stringReverse(strArray);
putchar('\n');
return 0;
}
void stringReverse(char strArray[])
{
if (*strArray != '\0') {
stringReverse(strArray + 1);
putchar(*strArray);
}
}
Program output:
.sdrawkcab gnirts siht tnirP
First, you need to return an value.
Then, what your algorithm should to do? Run until the final of your string and then return variable by variable in reverse with just one parameter, well you just need pass this parameter shorter every loop.
Like this:
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void stringReverse(char strArray[], int i) {
if (strArray[0] != NULL)
if (strArray[0] != '\0') {
int c = 0;
char str[30];
while (c < strlen(strArray)) {
str[c] = strArray[2 + c -1];
c++;
}
str[c] = '\0';
stringReverse(str);
}
printf("%c", strArray[0]);
}
int main(int argc, char *argv[]) {
char strArray[30] = "Print this string backward.";
stringReverse(strArray, 0);
printf("\n\n");
system("Pause");
return(0);
}
I am trying to concatenate two strings in C and receive a "Thread 1: signal SIGABRT" error.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
int main() {
char name[50];
ifile = fopen("stats.list", "r");
for(;;) {
fscanf(ifile, "%s%f%f", name, &sky, &stddev);
if (feof(ifile))
break;
char ext[5] = ".par";
dataparsFile = strcat(name, ext);
dataparsFile = fopen(dataparsFile, "w");
fprintf(dataparsFile, "%s\n",
"stuff gets read in to file named after new string";
fprintf(ofile, "phot ");
fprintf(ofile, "%s%s%s%s%s%s \n",
", datapars=", dataparsFile);
}
fclose(ifile);
fclose(ofile);
The goal of the code is to take an image name that is read in and add on the .par extension. Then, I want to open a file with that name of image+.par and write into it. Since I will have a couple hundred such files, I need to loop through them with the name changing each time.
The problem is name is not initialized. You see, in c strings use a convention, they are any sequence of ASCII (probably some other printable characters, but in principle just ASCII) that must be followed by a '\0' byte that marks the end of the string.
Your name array doesn't have this '\0' so strcat() tries to find it but it fails and perhaps it reads beyond the end of the array, although anyway reading uninitialized data is undefined behavior.
The way strcat(dst, src) works is pretty much like this
char *
strcat(char *const dst, char *src)
{
// Make a pointer to keep dst's address
// unchanged and return it
char *ptr = dst;
// Compute search for the end of the destination
// string to start copying there
while (*ptr != '\0')
ptr++;
// Copy all the characters from `src' until the '\0'
// occurs
while (*src != '\0')
*(ptr++) = *(src++);
*ptr = '\0';
return dst;
}
As you see, this is very inefficient if you call strcat() many times, and it will certainly not work if you pass either of the parameters before initializing it.
In fact, it's terribly unsafe because there is no bound checking, the caller has to make sure that the destination array is large enough to hold both strings.
I'm creating a char* which essentially will be treated as an string. The string is suppose to be used over and over again. Everytime I'm attempting to check with the while loop and see if its correct to the "quit"...
*I keep getting a segmentation fault...What am I doing wrong -- Pretty idiotic mistake - possibly?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* input = (char*)malloc(sizeof(char));
input = "CONTINUE";
while(strcmp(input, "quit") != 0)
{
printf("%s", "System: ");
scanf("%s", input);
}
return 0;
}
Two problems I see in first look:
char* input = (char*)malloc(sizeof(char));
You are assigning your pointer a memory of just one character. It should have enough memory to hold your string not just one character.
You should copy the string in to the allocated buffer using strcpy. Not aassign a string literal to your pointer. Note that modifying such a string literal results in Undefined Behavior.
input = "CONTINUE";
Correct way of doing the above 2 are:
char* input = (char*)malloc(sizeof(MAX_LENGTH));
strcpy(input, "YOURSTRING");
Where MAX_LENGTH is sufficient to hold your input strings.
You are trying to change a literal which is illegal.
Try:
char* input = (char*)malloc(sizeof(char)); /* You need more than one char. */
char* input = (char*)malloc(LENGTH); /* Allocate `LENGTH` chars. */
input = "CONTINUE"; /* You can't write (scanf) over a string literal. */
strcpy(input, "CONTINUE"); /* Now it's legal to write over `input`. */
Other points to watch out for:
Using scanf with a bare "%s" is unsafe. You should use something like "%10s" to make sure a potentially malicious user doesn't enter more than 10 characters
Did you know sizeof(char) isn't needed since it's guaranteed to be 1 ?
I have to compare few characters of string say from 2nd char till 4th character( counting starts from zero)
The string is stored in elements of structure say zoopla->real
for example zoopla ->real has '447889036' where real is of type char real[20];
Also please note I cant use function strnstr.
The code works as expected but just for curiousity, I have added printf statement and it shows me value till 4th cahr and then some garabe characters.
I want to know why the printf statment is showing 2 extra garabe values?
char * copyTemp;
char *strptr;
copyTemp = (char *)malloc(sizeof(char)*6);
strncpy(copyTemp, zoopla->real, 5);
printf("the string copied is %s", copyTemp); // debug statemnt
strptr = strstr(copyTemp, "666");
if(strptr != NULL)
{
//some other function
}
else
//some other function
free(copyTemp);
All criticism and suggestions are welcome
It seems to me that copyTemp is not null terminated. That's why printf shows you garbage characters after the characters you put in there. It doesn't know where to stop so it continues iterate through memory.
Add
copyTemp[5] = '\0';
after strncpy.
See this example from the documentation of strncpy:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[6];
strncpy (str2,str1,5);
str2[5]='\0';
puts (str2);
return 0;
}
see
http://www.cplusplus.com/reference/clibrary/cstring/strncpy/
No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.
you have to add null your self.
if you will be allocating memory of constant size then use array only.
#include <stdio.h>
#include <string.h>
int main ()
{
char * copyTemp;
char *strptr;
copyTemp = (char *)calloc(sizeof(char),6);
strncpy(copyTemp, "88666782921", 5);
printf("the string copied is %s", copyTemp); // debug statemnt
strptr = strstr(copyTemp, "666");
if(strptr != NULL)
{
//some other function
}
else
//some other function
free(copyTemp);
return 0;
}
According to my old K&R, strncpy will only implicitly add null bytes if the source string has fewer characters than the number to be copied.
In this case, zoopla->real has more than 5 characters, so the function is simply copying the first five characters. Since you haven't initialized the memory to zero, or explicitly added a null byte, the string is not terminated after the fifth character. So when you print the string, you get additional bytes with essentially random values, until one is hit that happens to be zero.