When I try to use scanf() to read one string of chars, everything works.
In the code below, I read two strings of chars, but if I input "abcde abcde" (arbitrary letters), printf() prints " is your character".
int main(){
char A[5], B[5];
scanf("%s %s", A,B);
printf("%c is your character", A[0]);
}
What am I doing wrong?
You are typing one string of length 5 (+1 with \0) and try to put it in a char table of size 5, which is an undefined behavior.
If you want to put “abcde” in both A and B, you need to increase the size of A and B to at least 6.
As #pmg pointed out already, the char array has to be long enough to have the null-terminator at the end of it, thus abcde abcde doesn't work, but abcd abcd works. If you would like to solve this statically, literally just stretch the size of the array buy how much you need:
char A[40], B[40];
However, if you really insist on getting dynamic allocation, you could use getline(), then malloc on some char* of the length of your input string (worst case scenario), and then use sscanf to split your input stringo to A and B.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* I = NULL;
char* A;
char* B;
size_t len = 0;
if (getline(&I, &len, stdin) != EOF)
{
A = (char*)malloc(len + 1);
B = (char*)malloc(len + 1);
sscanf(I, "%s %s", A, B);
printf("%c is your character", A[0]);
free(A);
free(B);
}
free(I);
return 0;
}
Related
I'm trying to create a program that displays the string length of an entered string with a pointer to aforementioned string. When I input a string without spaces, the length is correct. When I enter a string with spaces, the length is incorrect. Please describe my mistake and recommend ways to fix it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int l,n;
char s[n], *p=s;
*p = malloc(sizeof(char)*5);
n = sizeof(*p);
if (p==NULL)
printf("Unable to allocate memory");
printf("Input a string: ");
scanf("%s", p);
l = strlen(p);
printf("\nLength of given string: %d\n", l);
}
Input:
Input a string: June 27
Output:
Length of given string: 4
Aside from the obvious memory allocation shortcomings mentioned in the comments, "%s" used with scanf will read up to the first whitespace. If you want to read complete lines (up to newline), consider using fgets instead.
The program has the following defects:
The variable n is uninitialized before its usage in char s[n].
You're trying to read the whole line by scanf() which only reads to the next whitespace.
Allocated memory of 5 length, which is an overflow and tends to Undefined Behavior.
The (char *) is not explicitly defined during memory allocation.
Code redefined:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int main(void) {
char *s;
s = (char *)malloc(sizeof(char) * MAX); // allocating memory correctly
if (s == NULL) {
printf("Memory allocation failed.\n");
return -1;
}
printf("Enter a string: ");
fgets(s, MAX, stdin); // reading the entire line
size_t len = 0;
while (s[len++]); // alternative of strlen()
printf("String length is: %d\n", len);
return 0;
}
A sample output:
$ gcc -o prog prog.c; ./prog
Enter a string: Hello world, how are you today?
String length is: 33
Let's say I have the following string stored in char *m;
char *m = "K: someword\r\n";
The m will be inputed by the user so the user will write in the console:
K: someword\r\n
The someword can have different length, while K: \r\n will always be the same.
Now my question is, which is the best way after I read this input to extract someword from it and save it into a new char* variable?
Use sscanf() like this:
#include <stdio.h>
int main (void)
{
char buffer [50], k, return_car, new_line;
int n = sscanf ("K: someword\r\n", "%c: %s%c%c", &k, buffer, &return_car, &new_line);
printf ("The word is \"%s\". sscanf() read %d items.\n", buffer, n);
return 0;
}
Output:
The word is "someword". sscanf() read 4 items
Since both the substrings we aren't interested in ("K: " and "\r\n") are of fixed length, you can do this:
char *s;
size_t len = strlen(m);
s = malloc(len);
strcpy(s, m + 3);
s[len - 4] = 0;
printf("%s\n", s);
free(s);
Note that I declared a new char * variable to copy to since m is in read-only memory, and that robust code would handle the case where malloc failed and returned NULL.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *m = "K: someword\r\n";
const size_t someword_len = strlen(&m[3]);
char *someword = malloc(someword_len);
if (someword == NULL) { fprintf(stderr, "Malloc error\n"); abort(); }
memcpy(someword, &m[3], someword_len - 2);
someword[someword_len - 1] = '\0';
puts(someword);
free(someword);
}
You assume that string m always starts with "K: " (that's 3 characters) and ends with "\r\n" (that's two characters).
I believe strlen(m) will be faster then strchr(m, '\r') or strrchr(m, '\r') on most platforms
After you have the length of the string, using memcpy instead of strcpy will be faster.
Remember to null terminate your string
Remember to handle errors.
#include <stdio.h>
void reverse(int len, char s[], char b[]);
int main() {
char s[5] = "hello";
char b[5];
reverse(5, s, b);
return 0;
}
void reverse(int len, char s[], char b[]) {
int i;
for (i = 0; i < len; i++) {
b[(len - 1) - i] = s[i];
}
printf("%s : %s\n", s, b);
printf("%s", b);
}
Here is my code above in C. When I run it, it switches the string s[] to b[] but b[]also includes s[]. Can someone please thoroughly explain what I'm doing wrong? I really appreciate it.
char s[5] = "hello";
This is wrong, you need one more [6] in order to store the trailing '\0' (same for b)
It's better to omit the array size:
char s[] = "hello";
char b[sizeof(s)];
And you need b[i] = '\0'; after the for loop.
Your string buffers are too small, they must be six characters or more to hold the string "hello". Remember that strings C have a terminating '\0'-character at the end; that won't fit with space for only five characters.
Also, when reversing you never copy the terminating character.
You need b[len - 1] = '\0'; before exiting reverse().
When you pass non-terminated strings to printf()'s "%s" format, you get undefined behavior. Typically it "runs off the end" of the string, printing whatever it happens to find in memory, until it finds a character with the value 0 which causes it to stop.
The %s format specifier expects a string: An array of characters ending in a nul byte. You are not supplying that, so you are getting rubbish results. To hold a string with five characters, you need at least six chars.
every string in c is terminated by \0 which is a null character. so the array size should be enough to hold the string along with null character.
I will suggests to increase the size of array.
important :-
at the last assign b[last_index]='\0';
so that string b can be terminated by \0. otherwise it might give garbage values along with actual data while printing the string b.
In C, you just need to include
#include<string.h>
and use
strrev(a);
where a is the character array or string.
Whereas, your code can be modified too, to be written like this
#include <stdio.h>
void reverse(int len, char s[], char b[]);
int main() {
char s[5] = "hello";
char b[5];
reverse(5, s, b);
return 0;
}
void reverse(int len, char s[], char b[]) {
int i,j;
for (i = 0,j=len-1; i <=j; i++, j--) {
b[j]=a[i];
}
printf("%s : %s\n", s, b);
printf("%s", b);
}
I am a newbie in c programming language and I have a university tutorial assignment that is related with working with chars(I wont be graded for this assignment) where you have to count words, I have to compile and submit my answers in an online web environment where my code will run against test cases that are not visible to me.here is my assignment:
Write the function 'wc' which returns a string containing formatted as follows: "NUMLINES NUMWORDS NUMCHARS NUMBYTES" .
Whitespace characters are blanks, tabs (\t) and new lines (\n). A character is anything that is not whitespace. The given string is null-char (\0) terminated.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* wc(char* data) {
char* result ;
int numLine ;
int numWords ;
int numChars ;
int i;
int numBytes =strlen(data);
char* empty=NULL;
while(strstr(data,empty)>0){
numWords=1;
for (i = 0; i < sizeof(data); i++) {
if(data[i]=='\n'){
numLine++;
}
if(data[i]==' ' ){
numWords++;
}
if(data[i]!=' '){
numChars++;
}
}
}
sprintf(result, "%d %d %d %d", numLine, numWords, numChars, numBytes);
return result;
}
this code will give me the correct output result but I am missing something here at least the test tells me that.
You've got a very serious error:
char* result;
...
sprintf(result, "%d %d %d %d", numLine, numWords, numChars, numBytes);
This is not allowed in C. You need to allocate sufficient memory for the string first. Declare result as a large enough static array, or use malloc if you've covered that in your course.
e.g.
char buf[100]; // temporary buffer
sprintf(buf, "%d %d %d %d", numLine, numWords, numChars, numBytes);
char *result = malloc(strlen(buf) + 1); // just enough for the string
strcpy(result, buf); // store the string
return result;
What if you have this input?
Two Words.
You have to count the transitions between whitespace/non-whitespace, not just count spaces.
Also, I'm pretty sure strstr(data,NULL) will not do anything useful.
You also appear to be missing the \t for tab in your white space checker, and you're not correctly checking when you're in or out of a word. You can use the boolean type bool for this defined in stdbool.h for this.
Source code of wc unix command:
http://www.gnu.org/software/cflow/manual/html_node/Source-of-wc-command.html
All test cases handled.
1) sizeof is wrong:
Instead of sizeof operator you need to use strlen() in for loop, like:
for (i = 0; i < strlen(data); i++)
^ not sizeof
sizeof(data) returns only size of data pointer address that is 4. Because you are to read all char in data[] you need strlen() that will return length of data[] (or number of chars in data[])
2) memory error:
Next Error I can notice there is no memory allocated for result. it declare like:
char* result ;
and No memory allocate! and you are writing using sprintf that cause undefined behavior of your code
3) while(strstr(data,empty)>0) is wrong
strstr() search position of a string in to other you empty string is NULL , CHECK:
char *strstr(const char *s1, const char *s2);
you strstr() always returns data, Why are you calling this? I believe you don't need this while() loop.
I improved you code upto some extend as below, There was only three error as I mentioned above now corrected(to understand read comments), You basic algo is correct:
#define SIZE 256 // added size macro
char* wc(char* data)
char* result = malloc(SIZE*sizeof(char)); //(2) allocated memory for result
int numLine ;
int numWords ;
int numChars ;
int i;
int numBytes =strlen(data);
numWords=1;
// (3) remove while loop
for (i = 0; i < strlen(data); i++) { //(1) change size
if(data[i]=='\n'){
numLine++;
}
if(data[i]==' ' ){
numWords++;
}
if(data[i]!=' '){
numChars++;
}
}
sprintf(result, "%d %d %d %d", numLine, numWords, numChars, numBytes);
return result;
}
int main(){
printf("\nresult: %s\n", wc("q toei lxlckmc \t \n ldklkjjls \n i \t nn "));
return 1;
}
Output:
result: 2 14 28 41
see
char str[] = "hello world";
printf("%s",str);
printf statement prints the all character in string before reaching '\0'
so what if i want to print just 4 1st character of str on stdout?
You can just specify the field width in the printf format string:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
printf("%.4s\n", s);
return 0;
}
or, if you want to specify the field width at run-time:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
const int fw = 4;
printf("%.*s\n", fw, s);
return 0;
}
In either case the output will be:
Hell
You can use %c in your format string:
printf("%c", *s);
prints 'H'
To print an arbitrary char:
printf("%c", s[3]);
prints 'l'
For the first character, you can just use:
printf ("%c", *str); // or
printf ("%c", *(str+0)); // or
printf ("%c", str[0]);
For a different character, just reach out and grab it by using an offset. For the second l at offset 3:
printf ("%c", str[3]); // or
printf ("%c", *(str+3));
For a substring, you can use a combination of that method along with the maximum field width feature of printf:
printf ("%.2s", str+3); // prints "lo"
With all these solutions, you want to make sure you don't start on the wrong side of the null terminator. That wouldn't be a good thing :-)
If you want a generalised solution that will work for any string, and is relatively safe in terms of finding the starting point, you can use:
void outSubstr (FILE *fh, char *str, size_t start, size_t sz, int padOut) {
if (start >= strlen (str)) {
if (padOut)
fprintf (fh, "%*s", sz, "");
return;
}
if (padOut)
fprintf (fh, "%-*.*s", sz, sz, str + start);
else
fprintf (fh, "%-.*s", sz, str + start);
}
The parameters are as follows:
fh is the file handle to write to.
str is the start of the string.
start is the offset to start printing from.
sz is the maximum number of characters to print.
padOut is a flag indicating that sz is also the minimum size. Output will be padded with spaces on the right if there are not enough characters in the string to satisfy the size.
This will print up to 4 characters.
printf("%.4s", str);
there is also a "substr()" function
that return the substring from complete string.
example
printf("%s",substr(str,0,4));
it has syntax like this
substr(arrayName,charStartingPosition, lengthOfCharacters);
i hope this is easy to understand and no need to write more than 1 statement.
Really less painful for the system :
int main(void)
{
char c;
c = 'z';
write(1, &c, 1);
}
No need for heavy stdio here
Then you can ...
char *s = "Hello, World!";
write(1, s, numberOfChars);
Or if you really want to do it char by char:
void printnchars(char *s, int n)
{
int i;
i = 0;
while (i <= n)
{
write(1, s + i, 1);
i++;
}
}
numOfChars = 4;
printf("%.*s\n", numOfChars, "Hello, world!");
Where numOfChars is the quantity of characters that you want to print.