在 C 中,有没有办法将 void 指针转换为定义的大小类型?
In C, is there a way to cast a void pointer to a defined size type?
我需要一个“通用”scanf 函数来验证输入,同时还为指令和错误打印一条消息。扫描是一个接受空指针的函数,它是将存储输入值、类型说明符和消息的变量的方向。代码如下所示:
void scan(char specifier, void *dest, string instruction, string error) {
bool success = true;
do {
if(!success) {
while (getchar()!='\n');
perror(error);
}
puts(instruction);
switch (specifier)
{
case 'd':
success = scanf(" %d", (int *)dest);
break;
case 's’:
// In this particular program I need the strings to be 30 bytes with spaces.
success = scanf(“ %29[^\n]s", (char *)dest);
break;
case 'h':
success = scanf(" %hd", (short *)dest);
break;
case 'f':
success = scanf(" %f", (float *)dest);
break;
}
} while (!success ); }
但是是否可以将 void 指针转换为给定大小类型的指针而不是 switch
?像这样:
double myVar;
size_t varSize = sizeof(double); void * dest = &myVar;
// specifierForDest is a string
scanf(specifierForDest, (varSize *)dest);
因此 dest
成为指向大小为 varSize
的变量的指针。
或者比在 C 中为每个类型编写 case
更好的任何其他已知方法?
C 标准不提供将指针动态转换为 scanf
所需指针类型的方法。这意味着,一旦您的函数接收到 void *
参数,将其转换为指定接收的 scanf
类型的唯一方法是将它们作为个别情况处理。
另一种方法是不以 void *
形式接收参数,而是在可变参数列表中接收它并将其转发给专为此类操作设计的 vscanf
。为此,您必须将目标参数移动到参数列表的末尾。下面是示例代码。可变参数列表处理在最后几行。
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
typedef char *string;
void scan(char specifier, string instruction, string error,...)
{
bool success = true;
do
{
if (!success)
{
int c;
do
c = getchar();
while (c != EOF && c != '\n');
perror(error);
}
puts(instruction);
char *specifierForDest;
switch (specifier)
{
case 'd': specifierForDest = " %d"; break;
case 's': specifierForDest = " %30[^\n]"; break;
case 'h': specifierForDest = " %hd"; break;
case 'f': specifierForDest = " %f"; break;
default:
; // Do something here; do not neglect error cases.
}
va_list ap; // Create argument list pointer.
va_start(ap, error); // Initialize argument list handling.
success = 1 == vscanf(specifierForDest, ap);
// Forward argument to vscanf.
va_end(ap); // Clean up argument list handling.
} while (!success);
}
谢谢。根据您的所有建议,我想出了这个:
#include <stdarg.h>
#include <stdlib.h>
typedef char string[30];
void scan(string specifier, string instruction, string error, ...) {
bool success = true;
va_list ap; va_start(ap, error);
do {
if(!success) {
int c;
do
c = getchar();
while (c != EOF && c != '\n');
puts(error);
}
puts(instruction);
success = vscanf(specifier, ap);
} while (!success );
va_end(ap); }
效果很好。
我需要一个“通用”scanf 函数来验证输入,同时还为指令和错误打印一条消息。扫描是一个接受空指针的函数,它是将存储输入值、类型说明符和消息的变量的方向。代码如下所示:
void scan(char specifier, void *dest, string instruction, string error) {
bool success = true;
do {
if(!success) {
while (getchar()!='\n');
perror(error);
}
puts(instruction);
switch (specifier)
{
case 'd':
success = scanf(" %d", (int *)dest);
break;
case 's’:
// In this particular program I need the strings to be 30 bytes with spaces.
success = scanf(“ %29[^\n]s", (char *)dest);
break;
case 'h':
success = scanf(" %hd", (short *)dest);
break;
case 'f':
success = scanf(" %f", (float *)dest);
break;
}
} while (!success ); }
但是是否可以将 void 指针转换为给定大小类型的指针而不是 switch
?像这样:
double myVar;
size_t varSize = sizeof(double); void * dest = &myVar;
// specifierForDest is a string
scanf(specifierForDest, (varSize *)dest);
因此 dest
成为指向大小为 varSize
的变量的指针。
或者比在 C 中为每个类型编写 case
更好的任何其他已知方法?
C 标准不提供将指针动态转换为 scanf
所需指针类型的方法。这意味着,一旦您的函数接收到 void *
参数,将其转换为指定接收的 scanf
类型的唯一方法是将它们作为个别情况处理。
另一种方法是不以 void *
形式接收参数,而是在可变参数列表中接收它并将其转发给专为此类操作设计的 vscanf
。为此,您必须将目标参数移动到参数列表的末尾。下面是示例代码。可变参数列表处理在最后几行。
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
typedef char *string;
void scan(char specifier, string instruction, string error,...)
{
bool success = true;
do
{
if (!success)
{
int c;
do
c = getchar();
while (c != EOF && c != '\n');
perror(error);
}
puts(instruction);
char *specifierForDest;
switch (specifier)
{
case 'd': specifierForDest = " %d"; break;
case 's': specifierForDest = " %30[^\n]"; break;
case 'h': specifierForDest = " %hd"; break;
case 'f': specifierForDest = " %f"; break;
default:
; // Do something here; do not neglect error cases.
}
va_list ap; // Create argument list pointer.
va_start(ap, error); // Initialize argument list handling.
success = 1 == vscanf(specifierForDest, ap);
// Forward argument to vscanf.
va_end(ap); // Clean up argument list handling.
} while (!success);
}
谢谢。根据您的所有建议,我想出了这个:
#include <stdarg.h>
#include <stdlib.h>
typedef char string[30];
void scan(string specifier, string instruction, string error, ...) {
bool success = true;
va_list ap; va_start(ap, error);
do {
if(!success) {
int c;
do
c = getchar();
while (c != EOF && c != '\n');
puts(error);
}
puts(instruction);
success = vscanf(specifier, ap);
} while (!success );
va_end(ap); }
效果很好。