标签: stdio

在C中尝试和真正的简单文件复制代码?

这看起来像一个简单的问题,但我在这里找不到类似的东西.

由于C中没有文件复制功能,我们必须自己实现文件复制,但我不喜欢重新发明轮子,即使是那样的琐碎事情,所以我想问云:

  1. 您建议使用fopen()/ fread()/ fwrite()进行文件复制的代码是什么?
    • 您建议使用open()/ read()/ write()进行文件复制的代码是什么?

此代码应该是可移植(在Windows/MAC/LINUX/BSD/QNX/younameit),稳定的,经过时间考验的,速度快,内存使用效率等进入特定系统的内部挤出一些性能是值得欢迎的(就像得到文件系统的簇大小) .

这似乎是一个微不足道的问题,但是,例如,CP命令的源代码不是10行C代码.

c file-io copy stdio

9
推荐指数
2
解决办法
1万
查看次数

使用读取模式打开的流的fputc()行为

我无法找到任何对使用fputc()时创建流的指定行为的引用fopen("/some/path", "r").

我搜索了C11草案n1570 pdf寻找没有运气的任何参考,fopen()功能规范谈到将未知字符作为模式参数传递,这是未定义的行为.但它没有说明创建的流上的后续IO.

这是fwrite()功能规范

7.21.8.2 fwrite功能

概要

  1. #include <stdio.h>
    size_t fwrite(const void * restrict ptr,
        size_t size, size_t nmemb, FILE * restrict stream);
    
    Run Code Online (Sandbox Code Playgroud)

描述

  1. fwrite函数写入,从阵列所指向的ptr,最多nmemb,其大小由指定的元素size,到流指向stream.对于每个对象,对fputc函数进行大小调用,从unsigned char完全覆盖对象的数组中获取值(按顺序).流的文件位置指示符(如果已定义)按成功写入的字符数提前.如果发生错误,则流的文件位置指示符的结果值是不确定的.

返回

  1. fwrite函数返回成功写入的元素数,这将少于nmemb仅在遇到写入错误时.如果为sizenmemb为零,则fwrite返回零,并且流的状态保持不变.

这需要我们的fputc()功能,所以

7.21.7.3 fputc功能

概要

  1. #include <stdio.h>
    int fputc(int c, FILE *stream);
    
    Run Code Online (Sandbox Code Playgroud)

描述

  1. fputc …

c fopen stdio undefined-behavior language-lawyer

9
推荐指数
1
解决办法
174
查看次数

从stdio文件写入函数处理返回值有什么好的编程模式

我正在研究一些产生大量代码的代码

ignoring return value of ‘size_t fwrite(const void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result
Run Code Online (Sandbox Code Playgroud)

使用g ++编译时出现警告,我想知道实际记录和处理大量单独顺序fwrites 的返回值的最佳编程模式(即fwrite在循环中不一样)

让我们说代码现在看起来像这样:

fwrite (&blah, sizeof (blah), 1, fp);
// ... more code ...
fwrite (&foo, sizeof (foo), 1, fp);
// ... more code ...
Run Code Online (Sandbox Code Playgroud)

我正在考虑这样的事情,但我可能很难清理文件指针:

if (fwrite (&blah, sizeof (blah), 1, fp) != 1) return someerrorcode;
// ... more code ...
if (fwrite (&foo, sizeof (foo), 1, fp) != 1) return someerrorcode;
// ... more code ...
Run Code Online (Sandbox Code Playgroud)

我认为这种方法显然比嵌套更好,这太疯狂了:

if …
Run Code Online (Sandbox Code Playgroud)

c stdio

8
推荐指数
2
解决办法
4022
查看次数

如何为关闭的套接字捕获信号(`SIGPIPE`)?

我编写了一个服务器,它接受辅助端口上的套接字连接,以便传输通常发送的调试信息stderr.这个第二个端口 - 一个错误服务端口 - 一次只能有一个连接,这很方便,因为它允许我stderr使用一个dup2(2)调用重定向.(请参阅我是否可以将父进程的stderr重定向到分叉进程上的套接字文件描述符?).

以下代码在各方面都近乎令人满意.当客户端登录到端口时,stderr流将定向到套接字.当另一个客户端登录时,流再次被重定向,并且第一个客户端停止接收:完全令人满意.

在设计不足的情况下,当客户端关闭连接时,服务器崩溃,因为它正在尝试write()关闭的套接字.

我有一个正常的子进程的基本信号处理程序,但我不知道如何在错误套接字关闭时处理来自父进程的特定信号.

如何捕获ERR_PORT_NUM上的连接已关闭并让信号处理程序重新打开(或dup)stderr以/dev/null备下一个等待错误客户端的信号(在父级中)?

另外,当第二个连接时,我应该如何处理原始错误客户端连接?目前第一个客户是悬空.即使非正常关闭第一个连接也是可以接受的.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <netinet/in.h>
#include <sys/mman.h>

#define PORT_NUM 12345
#define ERR_PORT_NUM 54321

static void child_handler(int signum)
{
    switch (signum) {
        case SIGALRM:
            exit(EXIT_FAILURE);
            break;
        case SIGUSR1:
            exit(EXIT_SUCCESS);
            break;
        case SIGCHLD:
            exit(EXIT_FAILURE);
            break;
    }
} …
Run Code Online (Sandbox Code Playgroud)

sockets linux stdio

8
推荐指数
1
解决办法
1万
查看次数

C++输入性能

我试图在InterviewStreet上解决问题.一段时间后,我确定我实际上花了大量时间阅读输入.这个特殊的问题有很多输入,所以这有点意义.没有意义的是为什么不同的输入方法具有如此不同的表现:

最初我有:

std::string command;
std::cin >> command;
Run Code Online (Sandbox Code Playgroud)

更换它使它明显更快:

char command[5];
cin.ignore();
cin.read(command, 5);
Run Code Online (Sandbox Code Playgroud)

重写使用scanf的所有内容使其更快

char command;
scanf("get_%c", &command);
Run Code Online (Sandbox Code Playgroud)

总而言之,我把读取输入的时间减少了大约1/3.

我想知道这些不同方法之间的性能存在这样的差异.另外,我想知道为什么使用gprof没有强调我在I/O上花费的时间,而是似乎指责我的算法.

c++ performance profiling iostream stdio

8
推荐指数
1
解决办法
864
查看次数

Arduino:printf/fprintf打印问号而不是浮点数

我有一个Arduino草图的以下代码:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
static FILE lcdout = {0} ;

static int lcd_putchar(char ch, FILE* stream)
{
    lcd.write(ch) ;
    return (0) ;
}

void setup() {
  lcd.begin(16, 2);
  fdev_setup_stream (&lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE);
}

void loop() 
{
  stdout = &lcdout;
  printf("%.2f Volts", 2.0);
}
Run Code Online (Sandbox Code Playgroud)

问题出现在代码的最后一行.这应该打印出"2.00伏特",而是打印"?伏特"(问号而不是实际的浮点值).如果我尝试格式化整数,这很有用.

所以基本上,如果我用以下内容替换printf行,它将正常工作:

printf("%d Volts", 2); //prints correctly "2 Volts"
Run Code Online (Sandbox Code Playgroud)

知道问题是什么?

c printf arduino stdio

8
推荐指数
2
解决办法
1万
查看次数

mingw:使用-std = c ++ 11编译时找不到函数

我试图编译下面的代码(来自/sf/answers/33527231/).编译运行正常,如果我编译

$ g++ test.cpp
Run Code Online (Sandbox Code Playgroud)

但在使用-std=c++11开关时出错了:

$ g++ -std=c++11 test.cpp
test.cpp: In function 'std::string exec(char*)':
test.cpp:6:32: error: 'popen' was not declared in this scope
     FILE* pipe = popen(cmd, "r");
                                ^
Run Code Online (Sandbox Code Playgroud)

知道发生了什么事吗?

(我在mingw.org和WindowsXP64上使用mingw32 gcc4.8.1)

码:

#include <string>
#include <iostream>
#include <stdio.h>

std::string exec(char* cmd) {
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }
    pclose(pipe);
    return result;
}

int main() {}
Run Code Online (Sandbox Code Playgroud)

c++ mingw stdio popen c++11

8
推荐指数
1
解决办法
5888
查看次数

printf()在scanf()之后在行缓冲模式下将不带换行符的字符串打印到stdout

我知道大多数终端默认处于行缓冲模式.即输出被缓冲,并且在遇到换行字符之前不会被引导到stdout.

所以我希望它什么都不打印(至少在填充缓冲区之前):

int main() {
    while(1) {
        printf("Haha");
        sleep(1);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它确实在很短的时间内打印出来.

如果我想每秒打印"哈哈",我可以在printf之后printf("Haha\n")或者fflush(stdout)之后做.(我知道这不是那么便携,但它仍然是一个解决方案)

现在我回想起非常经典的scanf程序(我添加了while(1)循环以防止程序退出时缓冲区刷新):

int main() {
    char char_in;
    while(1) {
        printf("Haha. Input sth here: ");
        scanf("%c", &char_in);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在程序打印Haha. Input sth here:(并等待我的输入).如果我删除scanf语句,它不在这里.为什么会这样?

谢谢.

c stdio

8
推荐指数
1
解决办法
530
查看次数

如何从任何线程安全地使用 exit()

根据手册页 (2),该exit函数不是线程安全的: ,这是因为该函数尝试通过调用使用和MT-Unsafe race:exit注册的回调来清理资源(将数据刷新到磁盘、关闭文件描述符等...)。我希望我的程序能够做到这一点!(我的一个线程在整个程序的生命周期中保持文件描述符打开,所以这对我来说不是一个选择,因为我希望将所有数据写入输出文件)on_exitatexit_exit

我的问题如下:如果我很小心并且我不在线程之间共享任何敏感数据(如 fd),那么exit在多线程程序中调用是否“可接受”?请注意,我仅exit在发生不可恢复的错误时才调用。然而,当程序尝试退出时,我无法承受段错误。问题是,任何线程都可能发生不可恢复的错误......

我正在考虑使用 setjmp/longjmp “很好地”终止我的线程,但这会非常复杂,并且需要在我的代码中进行许多更改。

任何建议将不胜感激。谢谢 !:)

编辑:感谢@Ctx启发,我想出了以下想法:

#define EXIT(status) do { pthread_mutex_lock(&exit_mutex); exit(status); } while(0)

当然,exit_mutex 必须是全局的(外部)。

c multithreading stdio atexit thread-safety

8
推荐指数
1
解决办法
2940
查看次数

C - 编译程序时出现多个警告“指针缺少可空性类型说明符”,我该怎么办?

我最近开始在编译 C 程序时遇到问题,从stdio.hstdlib.h等不同的 C 包中收到 10、20 或 100 个警告。

警告有所不同,但通常是这样说的:

/usr/local/include/_stdio.h:93:16: warning: pointer is missing a nullability type specifier (_Nonnull, _Nullable, or
      _Null_unspecified) [-Wnullability-completeness]
        unsigned char   *_base;
Run Code Online (Sandbox Code Playgroud)

我的程序仍然可以编译并运行良好,但我担心这需要修复,而且在终端中收到所有这些警告也非常烦人。

我几乎可以肯定这些警告在我将系统更新到 macOS Catalina 后开始显示,但我不知道从哪里开始解决它。

更具体地说,当我像这样编译一个简单的helloworld.c程序时

#include <stdio.h>

int main (void) {
    printf("Hello World!"); 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

使用以下命令:

make helloworld 
Run Code Online (Sandbox Code Playgroud)

或者

gcc helloworld.c -o helloworld 
Run Code Online (Sandbox Code Playgroud)

..我收到以下警告,即使程序实际编译。

In file included from helloworld.c:1:
In file included from /usr/local/include/stdio.h:64:
/usr/local/include/_stdio.h:93:16: warning: pointer is missing a nullability type specifier (_Nonnull, _Nullable, …
Run Code Online (Sandbox Code Playgroud)

c macos stdio clang macos-catalina

8
推荐指数
1
解决办法
1978
查看次数