我是C的新手,我完成了一个小练习,它遍历传递给它的参数中的字母并识别元音。初始代码仅适用于一个参数(argv[1]
)。我想扩展它以便能够遍历argv[]
中的所有参数并重复识别元音的相同过程。
代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("ERROR: You need at least one argument.\n");
return 1;
}
if (argc == 2) {
int i = 0;
for (i = 0; argv[1][i] != '\0'; i++) {
char letter = argv[1][i];
if (letter == 'A' || letter == 'a') {
printf("%d: 'A'\n", i);
//so on
}
}
} else {
int i = 0;
int t = 2;
for (t = 2; argv[t] != '\0'; t++) {
for (i = 0; argv[t][i] != '\0'; i++) {
char letter = argv[t][i];
if //check for vowel
}
}
return 0;
}
}
我读了this answer,似乎最好的解决方案是使用指针,这个概念我仍然有点摇摇欲坠。我希望有人可以使用这个问题的上下文来帮助我更好地理解指针(通过解释在这个实例中如何使用指针解决手头的问题)。提前谢谢了。
答案 0 :(得分:4)
I was hoping someone could use the context of this question to help me understand pointers better....
在您的计划中:
int main(int argc, char *argv[])
首先,请在此处了解argc
和argv
的内容。
argc
(参数计数):是从命令行传入程序的参数数,包括程序名称。
argv
(参数向量):指向传递的字符串参数的字符指针数组。
关于argv
的几点:
argv[0]
指向的字符串代表程序名称。
argv[argc]
是一个空指针。
为了更好地理解,让我们考虑一个例子:
假设您正在将一些命令行参数传递给程序 -
# test have a nice day
test
是可执行文件的名称,have
,a
,nice
和day
是传递给它的参数,在这种情况下,参数计数(argc
)将为5
。
参数向量(argv
)的内存中视图将是这样的:
argv --
+----+ +-+-+-+-+--+ |
argv[0]| |--->|t|e|s|t|\0| |
| | +-+-+-+-+--+ |
+----+ +-+-+-+-+--+ |
argv[1]| |--->|h|a|v|e|\0| |
| | +-+-+-+-+--+ |
+----+ +-+--+ |
argv[2]| |--->|a|\0| > Null terminated char array (string)
| | +-+--+ |
+----+ +-+-+-+-+--+ |
argv[3]| |--->|n|i|c|e|\0| |
| | +-+-+-+-+--+ |
+----+ +-+-+-+--+ |
argv[4]| |--->|d|a|y|\0| |
| | +-+-+-+--+ |
+----+ --
argv[5]|NULL|
| |
+----+
关于字符串(以null结尾的字符数组)的注意事项,它将衰减为指向类型char*
的指针。
因为argv
(参数向量)是一个指向传递的字符串参数的指针数组。所以,
argv+0 --> will give address of first element of array.
argv+1 --> will give address of second element of array.
...
...
and so on.
我们也可以像这样得到数组第一个元素的地址 - &argv[0]
。
这意味着:
argv+0 and &argv[0] are same.
类似地,
argv+1 and &argv[1] are same.
argv+2 and &argv[2] are same.
...
...
and so on.
当您取消引用它们时,您将获得它们指向的字符串:
*(argv+0) --> "test"
*(argv+1) --> "have"
....
....
and so on.
类似地,
*(&argv[0]) --> "test"
*(&argv[0])
也可以写为argv[0]
。
表示:
*(argv+0) can also written as argv[0].
所以,
*(argv+0) and argv[0] are same
*(argv+1) and argv[1] are same
...
...
and so on.
打印时:
printf ("%s", argv[0]); //---> print "test"
printf ("%s", *(argv+0)); //---> print "test"
printf ("%s", argv[3]); //---> print "nice"
printf ("%s", *(argv+3)); //---> print "nice"
由于参数向量的最后一个元素是NULL
,当我们访问 - argv[argc]
时,我们得到NULL
。
访问字符串的字符:
argv[1] is a string --> "have"
argv[1][0] represents first character of string --> 'h'
As we have already seen:
argv[1] is same as *(argv+1)
So,
argv[1][0] is same as *(*(argv+1)+0)
要访问字符串“have”的第二个字符,您可以使用:
argv[1][1] --> 'a'
or,
*(*(argv+1)+1) --> 'a'
我希望这可以帮助你更好地理解你的问题背景中的指针。
要识别传递给程序的参数中的元音,您可以执行以下操作:
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("ERROR: You need at least one argument.\n");
return -1;
}
for (char **pargv = argv+1; *pargv != argv[argc]; pargv++) {
/* Explaination:
* Initialization -
* char **pargv = argv+1; --> pargv pointer pointing second element of argv
* The first element of argument vector is program name
* Condition -
* *pargv != argv[argc]; --> *pargv iterate to argv array
* argv[argc] represents NULL
* So, the condition is *pargv != NULL
* This condition (*pargv != argv[argc]) is for your understanding
* If using only *pragv is also okay
* Loop iterator increment -
* pargv++
*/
printf ("Vowels in string \"%s\" : ", *pargv);
for (char *ptr = *pargv; *ptr != '\0'; ptr++) {
if (*ptr == 'a' || *ptr == 'e' || *ptr == 'i' || *ptr == 'o' || *ptr == 'u'
|| *ptr == 'A' || *ptr == 'E' || *ptr == 'I' || *ptr == 'O' || *ptr == 'U') {
printf ("%c ", *ptr);
}
}
printf ("\n");
}
return 0;
}
输出:
#./a.out have a nice day
Vowels in string "have" : a e
Vowels in string "a" : a
Vowels in string "nice" : i e
Vowels in string "day" : a
答案 1 :(得分:2)
您可以使用嵌套for循环遍历所有参数。 argc
将告诉您参数的数量,而argv
包含数组数组。我还使用了strlen()
库中的strings
函数。它会告诉你字符串有多长。这样您就可以检查任意数量的参数。您的 if 语句也可以更改为2,argc
小于2或大于。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("ERROR: You need at least one argument.\n");
return 1;
} else {
int i, x;
int ch = 0;
for (i=1; i<argc; i++) {
for (x = 0; x < strlen(argv[i]); x++) {
ch = argv[i][x];
if (ch == 'A' || ch == 'a' || ch == 'e')
printf('Vowel\n');
}
}
}
}
Python等效于嵌套循环
for i in range (0, argc):
for x in range(0, len(argv[i])):
ch = argv[i][x];
if ch in ('A', 'a', 'e'):
print('Vowel')
答案 2 :(得分:1)
虽然您可以使用多个条件表达式来测试当前字符是否为元音,但创建一个包含要测试的集合的所有可能成员的常量字符串(此处为元音)并循环遍历您的元音串通常是有益的。确定当前字符是否匹配。
您可以简单地使用常量字符串作为要在strchr
调用中进行测试的字符串,以确定当前字符是否是该集合的成员。
以下简单地使用循环和指针迭代每个参数中的每个字符,并以类似的方式迭代我们的常量字符串char *vowels = "aeiouAEIOU";
中的每个字符,以确定当前字符是否是元音(处理低级和大写形式)。
#include <stdio.h>
int main (int argc, char *argv[]) {
int i, nvowels = 0;
char *vowels = "aeiouAEIOU";
if (argc < 2) {
fprintf (stderr, "ERROR: You need at least one argument.\n");
return 1;
}
for (i = 1; i < argc; i++) { /* loop over each argument */
char *p = argv[i]; /* pointer to 1st char in argv[i] */
int vowelsinarg = 0; /* vowels per argument (optional) */
while (*p) { /* loop over each char in arg */
char *v = vowels; /* pointer to 1st char in vowels */
while (*v) { /* loop over each char in vowels */
if (*v == *p) { /* if char is vowel */
vowelsinarg++; /* increment number */
break; /* bail */
}
v++; /* increment pointer to vowels */
}
p++; /* increment pointer to arg */
}
printf ("argv[%2d] : %-16s (%d vowels)\n", i, argv[i], vowelsinarg);
nvowels += vowelsinarg; /* update total number of vowels */
}
printf ("\n Total: %d vowles\n", nvowels);
return 0;
}
示例使用/输出
$ ./bin/argvowelcnt My dog has FLEAS.
argv[ 1] : My (0 vowels)
argv[ 2] : dog (1 vowels)
argv[ 3] : has (1 vowels)
argv[ 4] : FLEAS. (2 vowels)
Total: 4 vowles
如果您决定使用strchar
中的string.h
函数来检查当前字符是否在vowels
的集合中,则每个字符的内部循环将减少为:< / p>
while (*p) { /* loop over each char in arg */
if (strchr (vowels, *p)) /* check if char is in vowels */
vowelsinarg++; /* increment number */
p++; /* increment pointer to arg */
}
仔细看看,如果您有其他问题,请告诉我。
答案 3 :(得分:0)
如果其他人从 Learn C The Hard Way 中得到这个答案,上面使用指针的答案比我们领先一步,因为我们不会在第 15 章之前介绍指针。但是你可以用我们到目前为止所学的知识来做这个额外的功劳。我不会破坏乐趣,但您可以对参数使用 for 循环,对这些单词中的字母使用嵌套的 for 循环;从每个单词中获取一个字母就像 argv[j][i]
一样简单,其中 j 是传递的第 j 个参数,i 是 j 中的第 i 个字母。无需导入头文件或使用指针。我不得不说,当我在第 15 章中提到指针时,我确实回到了 H.S 的回答。