我正在尝试打印参数变量类型字符串,我一直坚持这个
尝试使用_Str[i] == '\0'
作为表达式在while循环中移动,并且EOF
返回(-1)定义为'\n' == EOF
之后我们在EOF
上进行测试返回int main(int argc, char** argv)
{
ps("test1", "test2");
return 0;
}
。而不是切换到下一个变量
#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_
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()
//
//
[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] $
// in your PauseButtonView
let object:[String:AnyObject] = [ "aParameter" : 42 ]
let startNotification = NSNotification(name: "startFunction:", object: object)
NSNotificationCenter.defaultCenter().postNotification(startNotification)
// in the view controller
func startFunction(notification:NSNotification)
{
let object = notification.object as? [String:AnyObject]
//...
}
我坚持这个并且不知道该怎么做,任何人都可以帮助我理解问题并解决它吗?
答案 0 :(得分:3)
正如mfro已经说过:你必须为你的功能找到一种方法来停止打印。此刻,您很高兴地超越了可变数组的范围。当putchar
返回EOF
时,您可以离开内部无限循环的唯一方法。可能会发生这种情况,但不太可能发生; putchar
仅在失败时返回EOF
;输出流没有结束,只要程序将数据注入其中,它就会运行。
(这与输入不同,输入在读取文件末尾或用户键入 Ctrl-D 时结束。例如,getchar
,EOF
是一种通常迟早会发生的情况。输出的情况并非如此。)
如果要实现可变参数函数,基本上有两种可能:前置计数:
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,您可以让编译器在没有哨兵时发出警告。这样做会更好,但仍然很难看,因为在函数调用结束时会有额外的信息。
如果将实现包装在可变参数宏中,则可以静默附加sentinel:
#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++);
}
这至少会给你关于传递非char指针的警告。
答案 1 :(得分:1)
有两种可能的解决方案。你要么争论参数列表的结尾:
#include <stdio.h>
#include <stdarg.h>
#define END_OF_LIST NULL
int ps1( const char* firstStr, ... )
{
va_list argptr;
va_start( argptr, firstStr );
const char* str = firstStr;
while ( str != END_OF_LIST ) // terminate if end of argument list
{
printf( "%s\n", str );
str = va_arg( argptr, const char* );
}
va_end( argptr );
return 1;
}
int test_C (void)
{
ps1( "test1", "test2", NULL );
// ^^^^ marke end of argument list
return 0;
}
或者你传递函数的参数数量:
int ps2( int count, ... )
{
va_list argptr;
va_start( argptr, count );
for( int i = 0; i < count; i++ ) // do "count" times
{
const char *str = va_arg( argptr, const char* );
printf( "%s\n", str );
}
va_end( argptr );
return 1;
}
int main (void)
{
ps2( 2, "test1", "test2" );
// ^ number of arguments
return 0;
}
最后功能ps
与putchar
:
#define EOF -1
int ps( const char* firstStr, ... )
{
va_list argptr;
va_start( argptr, firstStr );
const char* str = firstStr;
while ( str != END_OF_LIST )
{
int i = 0;
while ( str[i] )
{
if( putchar( str[i]) == EOF )
return EOF;
i++;
}
if ( putchar( '\n' ) == EOF )
return EOF;
printf( "%s\n", str );
str = va_arg( argptr, const char* );
}
va_end( argptr );
return 1;
}