gpt4 book ai didi

c - 使用带可变参数的函数打印字符串 (va_list)

转载 作者:行者123 更新时间:2023-12-02 09:28:15 30 4
gpt4 key购买 nike

我正在尝试打印字符串类型的参数变量,但我一直卡在这上面

想法

尝试使用 _Str[i] 作为 while 循环内的表达式在 srting 内部移动,一旦 _Str[i] == '\0' 返回 (-1 ) 定义为 EOF,然后我们在 '\n' == EOF 上测试以返回 EOF。而不是切换到下一个变量

代码

主.c

int main(int argc, char** argv)
{
ps("test1", "test2");
return 0;
}

基础.h

#ifndef BASE_H_
#define BASE_H_
#ifndef EOF // (EOF) - End Of File character. (-1)
#define EOF (-1)
#endif// EOF
#include<stdio.h>// Facultatif
#include<stdarg.h>

int ps(const char* , ...); // our function


#endif // BASE_H_

基础.c

int ps(const char* _Str, ...)
{
int i = 0;

//char* string;
//va_list
//
va_list arg;
va_start(arg, _Str);

//for(i = 0; ; ++i)
// if(_Str[i] == '\0')
// putchar('\n');
while(1)
{
while(_Str[i])
{
if( putchar(_Str[i]) == EOF) //test on EOF value
{
return EOF;// (-1)
}//end if
i++;
}//end inner while
if(putchar('\n') == EOF) //occur right after we quit due to '\0'
{
return EOF;// (-1)
}//end if
string = va_arg(arg, char*);
}//end outter while

va_end(arg);
//
return 1; //to meet spec.
}// end ps()
//
//

使用 GCC 编译

[ar.lnx@host print] $ make
Building objects..
gcc -c -o main.o main.c -I. -Wall
Building objects..
gcc -c -o base.o base.c -I. -Wall
Building the application core..
gcc -o x main.o base.o -I. -g
Finish.
[ar.lnx@host print] $ ./x
Segmentation fault (core dumped)
[ar.lnx@host print] $

我被困在这个问题上,不知道该怎么做,谁能帮我理解并解决这个问题?

最佳答案

正如 mfro 所说:您必须为您的功能找到一种方法来停止打印。此刻,您愉快地走出了可变数组的界限。离开内部无限循环的唯一方法是 putchar 返回 EOF。这可能会发生,但可能性不大; putchar 仅在失败时返回 EOF;输出流没有尽头,只要您的程序向其中注入(inject)数据,它就会运行。

(这与输入不同,输入在读取文件末尾或用户键入 Ctrl-D 时结束。例如,getcharEOF 是一个通常迟早会发生的条件。输出不是这样。)

如果你想实现你的可变参数函数,你基本上有两种可能性:在前面加上一个计数:

ps(3, "Salut", "mon", "ami");

不附加一个标记值,通常是NULL:

ps("C'est", "la", "vie", NULL);

例如,哨兵变体:

void ps(const char *str, ...)
{
va_list arg;

va_start(arg, str);

while (str) {
puts(str);
str = va_arg(arg, const char *);
}

va_end(arg);
}

当然,您可能会忘记将标记放在末尾(或者,如果您选择计数变体,则会忘记更新计数)。使用 GCC 的 function attributes ,您可以让编译器在没有哨兵时发出警告。这样更好,但仍然很难看,因为函数调用末尾有额外的信息。

如果将实现包装在可变参数宏中,则可以静默附加哨兵:

#define ps(...) ps(__VA_ARGS__, NULL)

ps 将调用带标记的函数 ps。 (宏和函数使用不同的名称可能是个好主意。在这种情况下,通常会调用宏。)

仍然存在类型安全问题。没有人会阻止你像这样调用你的函数:

ps(1, 2, 3);

因为可变参数可以是任何类型。 (printf 函数依赖于格式正确的格式字符串来为所有参数找到正确的类型。)

因为我们已经进入了宏领域,您可以使用复合字面量来创建一个以 NULL 结尾的字符串数组:

#define ps(...) print_strings((const char *[]){__VA_ARGS__, NULL})

使用直接打印所有字符串的函数:

void print_strings(const char *str[])
{
while (*str) puts(*str++);
}

这至少会给您关于传递非字符指针的警告。

关于c - 使用带可变参数的函数打印字符串 (va_list),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35705186/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com