这年头搞 c 还有前途吗 看看我的 leetcode 第 151 题目 反转字符串 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzzkkk
V2EX    C

这年头搞 c 还有前途吗 看看我的 leetcode 第 151 题目 反转字符串

  •  
  •   zzzkkk 2023-09-15 15:23:46 +08:00 2998 次点击
    这是一个创建于 807 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include "stdio.h" #include "stdlib.h" #include "string.h" char * reverseWords(char * s){ char * start, * start2; start = s; whil(*start != '\0'){ start ++; } -- start; char s2[strlen(s)]; char * s2p = s2; while(start > s){ while(*start == ' ') start --; while(*start != ' ' && start >= s) start --; start2 = start; ++start2; while(*start2 != ' '){ *s2p++ = *start2++; } *s2p++ = ' ' ; } *s2p = '\0'; start = s; s2p = s2; while(*s2p!='\0') *start++ = *s2p++; *start = '\0'; return s; } int main(int argc, char ** argv){ char s[] = "abc edf ghi lkm opq rst "; printf("%s\n",reverseWords(s)); } 

    在 linux 机器上能编译运行正确 leetcode 提示==20==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000020 at pc 0x563392652f73 bp 0x7ffefb8e0c40 sp 0x7ffefb8e0c30 READ of size 1 at 0x602000000020 thread T0

    我是不是太贱了?

    18 条回复    2023-09-18 18:57:16 +08:00
    MoYi123
        1
    MoYi123  
       2023-09-15 15:28:44 +08:00   3
    2023 年了, 写 c/c++ 还不开 fsanitize 那确实
    zzzkkk
        2
    zzzkkk  
    OP
       2023-09-15 15:53:08 +08:00
    @MoYi123
    你感觉你能修复它吗?
    给 char s[] 里面加数字也没用
    lts9165
        3
    lts9165  
       2023-09-15 16:49:34 +08:00
    你把第 15 行的代码改成 while(start>=s && *start != ' ') start --; 就可以了,先判定界限
    zzzkkk
        4
    zzzkkk  
    OP
       2023-09-15 20:18:01 +08:00
    @lts9165
    这样写 c 太烦了
    反而增加了复杂度 这种 sanitize 还没只能到那种程度
    zzzkkk
        5
    zzzkkk  
    OP
       2023-09-15 20:32:47 +08:00 via Android
    c 这样搞 宁可学 rust
    standchan
        6
    standchan  
       2023-09-15 23:45:00 +08:00
    语言只是工具,这句话不知道今年重复了多少遍
    zzzkkk
        7
    zzzkkk  
    OP
       2023-09-16 09:50:57 +08:00
    是 leetcode 题目设计得不好 函数只传一个指针 还开 sanitize
    正常项目根本不可能这样设计

    下面这样就开了 sanitize 也运行正常

    ```c
    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"

    int main(int argc, char ** argv){

    char s[25] = "abc edf ghi lkm opq rst ";
    char * start, * start2;
    start = s;
    while( *start != '\0'){
    start ++;
    }
    -- start;
    char s2[strlen(s)+1];
    char * s2p = s2;
    while(start > s){
    while(*start == ' ' ) start --;
    while(start >= s && *start != ' ') start --;

    start2 = start;
    ++start2;

    while( *start2 != ' '){
    *s2p++ = *start2++;
    }
    *s2p++ = ' ' ;
    }
    *s2p = '\0';
    start = s;
    s2p = s2;
    while(*s2p!='\0') *start++ = *s2p++;
    *start = '\0';
    printf("%s\n", s);

    }

    ```
    ngloom
        8
    ngloom  
       2023-09-16 10:34:37 +08:00
    ```c
    char * reverseWords(char * s){
    char * a= s;
    char* b = s;
    while (*b) {
    b ++;
    }

    while(a != b) {
    char c = *a;

    }


    }
    ```
    ngloom
        9
    ngloom  
       2023-09-16 10:37:54 +08:00
    还没写完就误点回复了,
    印象里简单代码的做法是 一个指针指向头, 一个指针指向尾, 然后两个指针互换内容后接着相向移动, 直到相遇.
    zzzkkk
        10
    zzzkkk  
    OP
       2023-09-16 13:15:33 +08:00 via Android
    @ngloom
    你那样 单词内的字母顺序反了
    yanqiyu
        11
    yanqiyu  
       2023-09-17 05:47:57 +08:00
    倒序扣单词并不困难啊,维护两个 index ,一个头部一个尾部,寻找空格和非空格的边界就完了,哪用得着这么多 while

    这么写结构清晰很多,并且含义还容易理解

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

    void print_word(const char *str, size_t start, size_t stop) {
    for (size_t i = start; i < stop; i++) {
    // there is sth like %.*s but for simplicity ...
    printf("%c", str[i]);
    }
    }

    int main(int argc, char **argv) {
    char test_str[] = " f test sentence here bla bla ";
    size_t len = strlen(test_str) - 1;
    size_t start = len;
    size_t stop = len;
    // flag just for proper trailing space ...
    bool is_first_word = true;
    for (size_t i = len; i > 0; i--) {
    if (test_str[i] == ' ' && test_str[i - 1] != ' ') {
    stop = i;
    } else if (test_str[i] != ' ' && test_str[i - 1] == ' ') {
    start = i;
    if (is_first_word) {
    is_first_word = false;
    } else {
    printf(" ");
    }
    print_word(test_str, start, stop);
    }
    }
    return 0;
    }
    yanqiyu
        12
    yanqiyu  
       2023-09-17 06:08:04 +08:00
    @yanqiyu 洗了个澡发现边界情况写错了,修了(狗头)
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>

    void print_word(const char *str, size_t start, size_t stop) {
    for (size_t i = start; i <= stop; i++) {
    // there is sth like %.*s but for simplicity ...
    printf("%c", str[i]);
    }
    }

    int main(int argc, char **argv) {
    char test_str[] = " f test sentence here bla bla ";
    size_t len = strlen(test_str) - 1;
    size_t start = len;
    size_t stop = len;
    // flag just for proper trailing space ...
    bool is_first_wold = true;
    for (int i = len; i >= 0; i--) {
    if (i != 0 && test_str[i] == ' ' && (test_str[i - 1] != ' ')) {
    stop = i - 1;
    } else if (test_str[i] != ' ' && (i == 0 || test_str[i - 1] == ' ')) {
    start = i;
    if (is_first_wold) {
    is_first_wold = false;
    } else {
    printf(" ");
    }
    print_word(test_str, start, stop);
    }
    }
    return 0;
    }
    zzzkkk
        13
    zzzkkk  
    OP
       2023-09-17 11:22:21 +08:00
    @yanqiyu
    你这样是清晰了很多

    但还不算

    要弄个函数 reverseWords 返回 char *指针

    我刚才改了下你的代码 弄到 leetcode 还报错 除非把*s2p++ = ' ';的++去掉 但输出就不正确了


    ```c
    char * reverseWords(char * s){
    char * test_str = s;
    size_t len = strlen(test_str) - 1;
    size_t start = len;
    size_t stop = len;
    char * s2 = malloc(len + 1);
    char * s2p = s2;
    bool is_first_wold = true;
    for (int i = len; i >= 0; i--) {
    if (i != 0 && test_str[i] == ' ' && (test_str[i - 1] != ' ')) {
    stop = i - 1;
    } else if (test_str[i] != ' ' && (i == 0 || test_str[i - 1] == ' ')) {
    start = i;
    if (is_first_wold) {
    is_first_wold = false;
    } else {
    *s2p++ = ' ';
    }
    for ( int k = start; k <= stop; k ++){
    *s2p++ = test_str[k];
    }
    }
    }
    *s2p = '\0';
    s2p = s2;

    char * s3 = s;
    while(*s2p != '\0') {
    *s3 ++ = *s2p++;
    }
    *s3 = '\0';
    free(s2);
    return s;
    }
    ```
    colom
        14
    colom  
       2023-09-17 12:49:59 +08:00
    C 做题太难了,C++写着也不舒服,可惜我对其它的不熟
    zzzkkk
        15
    zzzkkk  
    OP
       2023-09-17 13:18:13 +08:00 via Android
    @colom
    那你用 c 做什么东西吃饭?
    底层 crud ?
    zzzkkk
        16
    zzzkkk  
    OP
       2023-09-17 23:44:45 +08:00 via Android
    @yanqiyu
    所以说 把那个++去掉就行 但留着++结果才正确 fsanitize 是不是报了假阳性
    ngloom
        17
    ngloom  
       2023-09-18 09:10:27 +08:00
    @zzzkkk 哦哦, 还真是, 审题不清, 果然越来越菜了. T.T
    weeei
        18
    weeei  
       2023-09-18 18:57:16 +08:00
    是必须自己实现 strstr(' ') 吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2232 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 15:57 PVG 23:57 LAX 07:57 JFK 10:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86