V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzzkkk
V2EX  ›  C

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

  •  
  •   zzzkkk · 2023-09-15 15:23:46 +08:00 · 2514 次点击
    这是一个创建于 469 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    char * reverseWords(char * s){
            char * start, *  start2;
            start = s;
            while(*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   ·   实用小工具   ·   2705 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:47 · PVG 13:47 · LAX 21:47 · JFK 00:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.