The C program below print the first and last character of 16 words strings:
#include<stdio.h>
#include<string.h>
void main()
{
char first, last;
char *str = "abcdefghijklmnop";
first = str[0];
last = str[15];
printf("%s", &first);
printf("%s", &last);
}
The output I am seeking is a and p. But, when I run this code I get the output:
apa
What am I doing wrong?
You're missing understanding of pointers. When you assign a character to first and last, then those characters will essentially be copied to first and last. Since first and last are distinct variables, their addresses have no relation to the char *str pointer. Also, printf("%s", &first); (and the same with last) invokes undefined behaviour, since printf expects a 0-terminated string, but you pass one character only, after which there's no zero terminator.
What you can do is either use pointers:
char *first = str + 0;
char *last = str + 15;
printf("%s %s", first, last);
This will print abcdefghijklmnop p
or to print the two chars only:
char first = str[0];
char last = str[15];
printf("%c %c", first, last);
This will print a p.
below lines will bring correct result
printf("%c", first );
printf("%c", last );
Your variables first and last are actual character values, not strings/pointers. You need to use %c instead. Try:
#include<stdio.h>
#include<string.h>
void main()
{
char first, last;
char *str = "abcdefghijklmnop";
first = str[0];
last = str[15];
printf("%c", first);
printf("%c", last);
}
The %s expects to get a pointer that points to an array of character values and keeps reading until it reaches a NULL character \0.
You can read more about this here http://pw1.netcom.com/~tjensen/ptr/ch3x.htm and here http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output.
I find that the following C++ page has a better diagrams for visualizing pointers http://cplusplus.com/doc/tutorial/pointers/.
Related
I'm trying to reproduce the behavior of the strstr() function, which tries to find a substring in a string and for that I created the following function and compared it to the original. I did the iterations all on paper to understand what was going on in the function, but I don't understand why the command return (&str[i]); prints ab and not just a. When the function enters in if (to_find[j] == '\0'), the values of i and j are 2 and 2, so it should just print &str[2], which is a. Why is printing ab instead of just a?
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char *ft_strstr(char *str, char *to_find)
{
int i;
int j;
i = 0;
if (*to_find == '\0')
return (str);
while (str[i] != '\0')
{
j = 0;
while (str[i + j] == to_find[j])
{
//printf("%d", i);
//printf("%d\n", j);
j++;
if (to_find[j] == '\0')
return (&str[i]);
}
i++;
}
return (0);
}
int main()
{
char i[] = "ab";
char dest[] = "a ab";
printf("%s", ft_strstr(dest, i));
//printf("%s", strstr(dest, i));
}
return (&str[i]); What this does is:
str[i] this is the same as *(str+i). It means take the address where str points to, add i to it and get its value.
&x means get the address of x
(&str[i]) Is a combination of the 2 above. It means take the address where str points to, add i to it and get its value and then get the address of that value. Which means the last 2 steps cancel each other out and you get: take the address where str points to, add i to it. It is the same as (str+i).
The return statement just means return this pointer.
Now after you called ft_strstr(dest, i) you get this pointer. In your case this pointer points to the second a in the string "a ab". You give this pointer to printf() and with the "%s" you told printf() to print the string where this pointer points to till there is a '\0'-byte. 'b' is not a '\0'-byte so it will also be printed.
The returned pointer points to here when you call printf():
V
+---+---+---+---+---+
| a | | a | b |\0 |
+---+---+---+---+---+
printf() will then check if it points to a '\0'-byte, which is false so the byte ('a') is printed and the pointer is incremented. Then the same is done for the byte ('b') and then it points to '\0', which means printf() stops here.
return (&str[i]); does not print anything. It just returns a value. And the value is the address to the i:th element of str.
The printing happens in printf("%s", ft_strstr(dest, i)); and what happens here is that you start with a format string, and the %s is a specifier that basically says "print characters until hitting the zero terminator, and start with the address specified".
When you print the return value from strstr using the specifier %s it will print "the needle" (aka the string to find) and all of the original string after the needle.
In your case there is nothing after the needle so your output is just "ab". Had your original string been "a abHelloWorld" your output would have been "abHelloWorld".
If you just want the first character of the needle do:
printf("%c", *ft_strstr(dest, i));
Also you can try this to get a better understanding:
char str[] = "Hello World";
printf("%s\n", str);
printf("%s\n", &str[0]);
printf("%s\n", &str[1]);
printf("%s\n", &str[2]);
printf("%s\n", &str[3]);
...
which will give you output
Hello World
Hello World
ello World
llo World
lo World
...
As you can see, printing from &str[n] will skip the first N characters and print the rest of the original string.
BTW:
char *ft_strstr(char *str, char *to_find)
should be
char *ft_strstr(const char *str, const char *to_find)
printf("%s", ...) prints a string, not a single character. To print a character, use the %c format specifier and provide the first element of the array as the argument:
printf("%c", *ft_strstr(dest, i));
Another option is to use putchar(...) for printing a single character.
For more information on printf format specifiers, see here.
Within this while loop
while (str[i + j] == to_find[j])
{
//printf("%d", i);
//printf("%d\n", j);
j++;
if (to_find[j] == '\0')
return (&str[i]);
}
the variable i is not being changed. It stays unchanged. It is the variable j that is being changed.
On the other hand the return statement
return (&str[i]);
returns a pointer to the symbol at the position i that is to the beginning of the substring equal to the string to_find.
{ay attention to that the array dest declared like
char dest[]="a ab";
in fact has the following content
char dest[] = { 'a', ' ', 'a', 'b', '\0' };
and the function returns a pointer to its substring
char dest[] = { 'a', ' ', 'a', 'b', '\0' };
^
|
{ 'a', 'b', '\0' }
that is a pointer to the first character of the string "ab" that is a substring of the string stored in the array dest.
Bear in main that when you write for example
printf( "%s\n", dest );
when this call is equivalent to
int i = 0;
printf( "%s\n", &dest[i] );
I input a string and then try to find an address of a char within the string but the problem is that I am unable to find the address of the same char in the string using pointers.
For example when input is "ALLEN" I need the addresses of both 'L's but my program only prints the address of the first 'L'.
I tried if ... else and a for-loop but I can't solve the problem.
#include <stdio.h>
#include <string.h>
main()
{
char a, str[81], *ptr;
printf("\nEnter a sentence:");
gets(str);
printf("\nEnter character to search for:");
a = getchar();
ptr = strchr(str,a);
/* return pointer to char*/
printf( "\nString starts at address: %d",str);
printf("\nFirst occurrence of the character (%c) is at address: %d ", a,ptr);
}
If I understood you correctly:
To find additional occurrences of the same character, just look for them after the last known occurrence. So, you would write something like this:
{
const char* next_occurrence = strchr(str, a);
while (next_occurrence != NULL) {
printf(
"Character %c occurs in string \"%s\" at position %p\n",
a, str, next_occurrence - str);
next_occurrence = strchr(next_occurrence + 1, a);
}
}
You'll note that next_occurrence + 1 is the address of the first character after the occurrence we've just found.
Just call strchr again:
ptr = strchr(str,a);
if (ptr != NULL)
ptr2 = strchr (ptr + 1, a);
Notice the first parameter to strchr is ptr + 1, so we start searching with the character after the one we already found.
I am encountering a problem while printing out a string using a while loop in a standalone function.
I have the following code:
#include <stdio.h>
int pword(char *);
int main() {
char s[] = "Alice";
pword(s);
return 0;
}
int pword(char *s) {
while(*s!='\0') {
printf("%s", s);
s++;
}
printf("\n");
return 0;
}
This is printing: Aliceliceicecee.
you're printing the offseted word each time, instead of the character.
Try changing (for instance)
printf("%s", s);
by
printf("%c", *s);
or since you don't really need formatting, use
putchar(*s);
(all this means that you're basically rewriting puts with a loop. So if no further processing is required on the characters, maybe you should just stick with standard functions)
%s means expect a const char * argument
%c means expect a character argument. The character argument is printed. Null characters are ignored;
You are looking for later one.
More info on %s: The argument is taken to be a string (character pointer), and characters from the string
are printed until a null character or until the number of characters indicated by the
precision specification is reached; however, if the precision is 0 or missing, all characters up to a null are printed;
Seeing no answer explained what exactly was going on, here is what you are actually doing:
int pword(char *s) { /* s = "Alice" (s is a char* that holds the address of "Alice" string)*/
while(*s!='\0') { /* check if the first char pointed to by s != '\0' */
printf("%s", s); /* print the string that start at s*/
s++; /* move s (the char pointer) 1 step forward*/
} /* s points to "lice" -> "ice" -> "ce" -> "e" */
printf("\n");
return 0;
}
In order to print the string "Alice" you could have just used printf("%s", s); as it would take the address pointed to by s, where "Alice" is stored, and print it until reaching null-terminator ('\0').
If you want to use a loop and print char by char, you should have used printf("%c", *s);. Using %c is meant for printing char where %s is for printing strings. Another thing to note is the s vs *s, where the former is a char* (pointer to char) that can hold number of consecutive chars, and the later (*s)is *(char*) i.e. dereferenced char*, that holds a single char.
To sum up:
print char by char
int pword(char *s) {
while(*s!='\0') {
printf("%c", *s);
s++;
}
printf("\n");
return 0;
}
print the whole string at once
int pword(char *s) {
printf("%s\n", s);
return 0;
}
If you want to print character by character, you should use *s in the printf statement like below.
#include <stdio.h>
int pword(char *);
int main() {
char s[] = "Alice";
pword(s);
return 0;
}
int pword(char *s) {
while(*s!='\0') {
printf("%c", *s);
s++;
}
printf("\n");
return 0;
}
I've been hung up on this for the past two hours, and it's really starting to irritate me. I'm using standard C, trying to print a char array's element.
The following is a snippet that works(prints entire array),
CreditCard validate_card(long long n) {
CreditCard cc; // specify new credit card
cc.n = n; // specify card num as passed
cc.valid = false; // initialize as invalid
cc.type = AEX; // initialize at american express
bool valid;
char s[20];
sprintf( s, "%d", n ); // convert credit card number into char array
printf("%s\n", s);
return cc;
}
The following snippet does not work,
CreditCard validate_card(long long n) {
CreditCard cc; // specify new credit card
cc.n = n; // specify card num as passed
cc.valid = false; // initialize as invalid
cc.type = AEX; // initialize at american express
bool valid;
char s[20];
sprintf( s, "%d", n ); // convert credit card number into char array
printf("%s\n", s[0]);
return cc;
}
On that note, if anyone could also too explain to me how to concatinate char array elements to char pointers, I'd be grateful.
When you use this line.
printf("%s\n", s[0]);
The compiler should print some warning about mismatch of the format string %s and the corresponding argument, s[0].
The type of s[0] is char, not char*.
What's your intention?
If you want to print just one character, use:
printf("%c\n", s[0]);
If you want to print the entire array of chracters, use:
printf("%s\n", s);
You need to replace below line
printf("%s\n", s[0]);
with
printf("%c\n", s[0]);
to print 1 character.
To print all characters 1 by 1, use a loop.
If you need to print only the first character of the array, you need to use %c, like
printf("%c\n", s[0]);
Take a look at this MSDN reference
I'm building a linked list and need your assistance please as I'm new to C.
I need to input a string that looks like this: (word)_#_(year)_#_(DEFINITION(UPPER CASE))
Ex: Enter a string
Input: invest_#_1945_#_TRADE
Basically I'm looking to build a function that scans the DEFINITION and give's me back the word it relates to.
Enter a word to search in the dictionary
Input: TRADE
Output: Found "TREADE" in the word "invest"
So far I managed to come up using the strtok() function but right now I'm not sure what to do about printing the first word then.
Here's what I could come up with:
char split(char words[99],char *p)
{
p=strtok(words, "_#_");
while (p!=NULL)
{
printf("%s\n",p);
p = strtok(NULL, "_#_");
}
return 0;
}
int main()
{
char hello[99];
char *s = NULL;
printf("Enter a string you want to split\n");
scanf("%s", hello);
split(hello,s);
return 0;
}
Any ideas on what should I do?
I reckon that your problem is how to extract the three bits of information from your formatted string.
The function strtok does not work as you think it does: The second argument is not a literal delimiting string, but a string that serves as a set of characters that are delimiters.
In your case, sscanf seems to be the better choice:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char *line = "invest_#_1945 _#_TRADE ";
char word[40];
int year;
char def[40];
int n;
n = sscanf(line, "%40[^_]_#_%d_#_%40s", word, &year, def);
if (n == 3) {
printf("word: %s\n", word);
printf("year: %d\n", year);
printf("def'n: %s\n", def);
} else {
printf("Unrecognized line.\n");
}
return 0;
}
The function sscanf examines a given string according to a given pattern. Roughly, that pattern consists of format specifiers that begin with a percent sign, of spaces which denote any amount of white-space characters (including none) and of other characters that have to be matched varbatim. The format specifiers yield a result, which has to be stored. Therefore, for each specifier, a result variable must be given after the format string.
In this case, there are several chunks:
%40[^_] reads up to 40 characters that are not the underscore into a char array. This is a special case of reading a string. Strings in sscanf are really words and may not contain white space. The underscore, however, would be part of a string, so in order not to eat up the underscore of the first delimiter, you have to use the notation [^(chars)], which means: Any sequence of chars that do not contain the given chars. (The caret does the negation here, [(chars)] would mean any sequence of the given chars.)
_#_ matches the first delimiter literally, i.e. only if the next chars are underscore hash mark, underscore.
%d reads a decimal number into an integer. Note that the adress of the integer has to be given here with &.
_#_ matches the second delimiter.
%40s reads a string of up to 40 non-whitespace characters into a char array.
The function returns the number of matched results, which should be three if the line is valid. The function sscanf can be cumbersome, but is probably your best bet here for quick and dirty input.
#include <stdio.h>
#include <string.h>
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
int main(){
char input[]="invest_#_1945_#_TRADE";
char *array[3];
char *p;
int i, size = sizeof(array)/sizeof(char*);
for(i=0, p=input;i<size;++i){
if(NULL!=(p=strtokByWord(p, "_#_"))){
array[i]=p;//strdup(p);
p=NULL;
} else {
array[i]=NULL;
break;
}
}
for(i = 0;i<size;++i)
printf("array[%d]=\"%s\"\n", i, array[i]);
/* result
array[0]="invest"
array[1]="1945"
array[2]="TRADE"
*/
return 0;
}