90 Intermediate C Programming
printf (" %d n" , v) ;10
printf (" %c n" , v) ;11
return EXIT _SUCCES S ;12
}13
The output of this program is:
55
7
Why do the two lines print different values, even though both use v? The first printf
treats v as an integer by using %d. Hence, the printed value is 55. The second printf treats
v as a character by using %c. Since 55 is the ASCII value of character 7’, 7 is printed on
screen. Note that in this case, using %c in printf causes the number 55 to be interpreted
as a character. C has different types, including char for characters and int for integers. A
char is an integer of a smaller range and can store one ASCII character. The character 7
has the value of 55. Even though they are both integers, the interpretations (%c or %d) are
different.
6.2.3 Finding Substrings: strstr
If string str1 is part of another string str2, we say str1 is a substring of str2. For
example, “str” is a substring of “structure” and “ure” is also a substring of “structure”.
“W” is a substring of “Welcome” but “sea” is not a substring of “sightseeing”.
If we want to determine whether one string is part of another string, we can use the
strstr function. This function takes two arguments: haystack and needle. The func-
tion attempts to locate needle within haystack. If needle is a substring of haystack,
strstr(haystack, needle) returns the address where the needle starts within haystack.
This address must not be NULL. If needle is not a substring of haystack, strstr(haystack,
needle) returns NULL. Please notice the order of the two arguments: The first is the longer
one. Here are two examples:
char haystack [] = { H , e , l , l , o , 0 };1
char * chptr ; // a p o i nte r2
chptr = strstr ( haystack , "llo ");3
// chptr s value is the address of haystac k [2]4
chptr = strstr ( haystack , "XY" );5
// chptr s value is NULL6
In the first call of strstr, “llo” is part of “Hello” and the “llo” starts at the third element
(index is 2). Thus, strstr returns & haystack[2]. In the second call of strstr, “XY” is
not part of “Hello” and chptr’s value is NULL. The ending character 0’ in haystack is not
considered when finding the needle.
6.2.4 Finding Characters: strchr
specific character. It returns the address of the first occurrence of the character within
the string. If this string does not contain the character, then strchr returns NULL. Here are
some examples:
char str [] = { H , e , l , l , o , 0 };1
char * chptr ; // a p o i nte r2
chptr = strchr ( str , H ); // chptr s value is str [0] s address3
Strings 91
chptr = strchr ( str , e ); // chptr s value is str [1] s address4
chptr = strchr ( str , l ); // chptr s value is str [2] s address5
chptr = strchr ( str , o ); // chptr s value is str [4] s address6
chptr = strchr ( str , t ); // chptr s value is NULL7
6.3 Understanding argv
The first example of Section 1.1 says that every C program starts at the special main
function
int main ( i n t argc , char * * argv )1
Adding spaces between *, or in front of argv makes no difference. The following two function
prototypes are exactly the same:
int main ( i n t argc , char * * argv )1
int main ( i n t argc , char ** argv )2
What is argv? As explained in the previous chapter and summarized in Table 4.1, adding
an asterisk after a type makes the type into a pointer. What does it mean if there are two
asterisks?
C has no special type for strings. C uses arrays of characters for strings, and the data in
those arrays must have the special property of being terminated by a null character: 0’.
As explained in the previous chapter, an array is a pointer. If you imagine that C had a
type for strings called string, this type would need to be equivalent to char * in real C
programs. If string were a type, then what would be the type for an array of strings? That
would be string *. Since string is actually char *, the type of string * is char * *.
The second argument of main, argv, is an array of strings. The first string in this array is
argv[0] and the type of argv[0] is char *. The first letter of the first string is argv[0][0].
The type of argv[0][0] is char. Please review Section 4.7 for the type rules.
How is this laid out in memory? If argv is an array of strings, where is the memory
holding the actual characters? When calling the main function, the arguments are provided
by the operating system, more precisely, by the shell program in the Terminal. Since main
is also a function, the arguments are stored on the call stack, as any other function.
Frame Symbol Address Value
main
argv 101 ?
argc 100 ?
This is how to execute a program called prog with some arguments:
$ ./prog some arguments
When running this program, “some” and “arguments” are called the command-line ar-
guments. We have been using command-line arguments for some time. For example, in
Section 1.1:
$ gcc prog1.c -o prog
Here gcc is a program; prog1.c -o prog are the arguments. There are four arguments,
including the gcc command itself. The program itself is always the first argument.
Let me go back to this command:
92 Intermediate C Programming
$ ./prog some arguments
There are three arguments so argc is 3, including ./prog itself. The value of argv is the
address of the first element, i.e., & argv[0]. Where is argv[0] stored? Before the main
function is called, the C runtime places it somewhere on the call stack. As usual, we do not
need to know where it is stored. We just need to know how to get the information: by using
argv[0] to get the first string.
The table below shows the call stack. The value of argv is the address of argv[0]. As
with all arrays, the addresses of argv[0], argv[1], and argv[2] are contiguous. For the
sake of explanation, we will use “-” for the values of argv[0], argv[1], and argv[2] for
the time being.
Frame Symbol Address Value
main
argv[2] 104 -
argv[1] 103 -
argv[0] 102 -
argv 101 102
argc 100 3
Since argv[0], argv[1], and argv[2] are strings, each of them is also a pointer storing
the starting address of the first letter in each of those strings. The value of argv[0] is the
address of argv[0][0]. To make it clearer a horizontal line separates the strings. Everything
still belongs to the same frame.
Frame Symbol Address Value
main
argv[0][6] 111 0’
argv[0][5] 110 g
argv[0][4] 109 o
argv[0][3] 108 r
argv[0][2] 107 p
argv[0][1] 106 /
argv[0][0] 105 .
argv[2] 104 -
argv[1] 103 -
argv[0] 102 105
argv 101 102
argc 100 3
In this example, the address of argv[0][0] is right above the address of argv[2].
However, it does not necessarily have to be this way. As previously mentioned, the value
of argv[0] is the address of argv[0][0]. Similarly, the value of argv[1] is the address of
argv[1][0]. The lower part of the call stack is skipped since it is the same as shown earlier.
Strings 93
Frame Symbol Address Value
main
argv[1][4] 116 0’
argv[1][3] 115 e
argv[1][2] 114 m
argv[1][1] 113 o
argv[1][0] 112 s
argv[0][6] 111 0’
argv[0][5] 110 g
argv[0][4] 109 o
argv[0][3] 108 r
argv[0][2] 107 p
argv[0][1] 106 /
argv[0][0] 105 .
Finally, here is the full frame on the call stack, showing all the arguments:
Frame Symbol Address Value
main
argv[2][3] 126 0’
argv[2][2] 125 s
argv[2][2] 124 t
argv[2][2] 123 n
argv[2][2] 122 e
argv[2][2] 121 m
argv[2][1] 120 u
argv[2][0] 119 g
argv[1][4] 118 r
argv[1][3] 117 a
argv[1][4] 116 0’
argv[1][3] 115 e
argv[1][2] 114 m
argv[1][1] 113 o
argv[1][0] 112 s
argv[0][6] 111 0’
argv[0][5] 110 g
argv[0][4] 109 o
argv[0][3] 108 r
argv[0][2] 107 p
argv[0][1] 106 /
argv[0][0] 105 .
argv[2] 104 117
argv[1] 103 112
argv[0] 102 105
argv 101 102
argc 100 3
6.4 Counting Substrings
Sometimes, we want to search a string and count the occurrences of a substring. For
example, “ice” is a substring of “nice” and it occurs only once. In the string, “This is his
history book”, the substring “is” occurs 4 times: “This is his history book”. The following
94 Intermediate C Programming
program combines what we have learned about strstr and argv to count the occurrences
of a substring.
/*1
* co u ntsubstr . c2
* count the occur r ence of a sub string3
* argv [1] is the longer string4
* argv [2] is the s h o r t e r string5
* argv [1] may contain space if the string enclosed by " "6
*/7
8
#in clude < stdio .h >9
#in clude < stdlib .h >10
#in clude < string .h >11
int main ( i n t argc , char * argv [])12
{13
int count = 0;14
char * ptr ;15
i f ( argc < 3)16
{17
printf (" Please enter two strings .n ");18
return EXIT _FAILUR E ;19
}20
printf (" argv [1] = %s , strlen = %d n" , argv [1] ,21
( i n t ) strlen ( argv [1]) );22
printf (" argv [2] = %s , strlen = %d n" , argv [2] ,23
( i n t ) strlen ( argv [2]) );24
ptr = argv [1];25
do26
{27
ptr = strstr ( ptr , argv [2]) ;28
i f ( ptr != NULL )29
{30
printf (" %s n" , ptr ) ;31
count ++;32
ptr ++;33
}34
} while ( ptr != NULL );35
i f ( count == 0)36
{37
printf (" argv [2] is not a substr i ng of argv [1]. n" );38
}39
e l s e40
{41
printf (" argv [2] occurs % d times in argv [1]. n" , count );42
}43
return EXIT _SUCCES S ;44
}45
This program is compiled and executed as follows:
$ gcc -g -Wall -Wshadow countstr.c -o countstr
$ ./countstr ”This is his history book.” is
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset