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

2023-09-15 15:23:46 +08:00
 zzzkkk
#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

我是不是太贱了?

2484 次点击
所在节点    C
18 条回复
MoYi123
2023-09-15 15:28:44 +08:00
2023 年了, 写 c/c++ 还不开 fsanitize 那确实
zzzkkk
2023-09-15 15:53:08 +08:00
@MoYi123
你感觉你能修复它吗?
给 char s[] 里面加数字也没用
lts9165
2023-09-15 16:49:34 +08:00
你把第 15 行的代码改成 while(start>=s && *start != ' ') start --; 就可以了,先判定界限
zzzkkk
2023-09-15 20:18:01 +08:00
@lts9165
这样写 c 太烦了
反而增加了复杂度 这种 sanitize 还没只能到那种程度
zzzkkk
2023-09-15 20:32:47 +08:00
c 这样搞 宁可学 rust
standchan
2023-09-15 23:45:00 +08:00
语言只是工具,这句话不知道今年重复了多少遍
zzzkkk
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
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
2023-09-16 10:37:54 +08:00
还没写完就误点回复了, 囧
印象里简单代码的做法是 一个指针指向头, 一个指针指向尾, 然后两个指针互换内容后接着相向移动, 直到相遇.
zzzkkk
2023-09-16 13:15:33 +08:00
@ngloom
你那样 单词内的字母顺序反了
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
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
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
2023-09-17 12:49:59 +08:00
C 做题太难了,C++写着也不舒服,可惜我对其它的不熟
zzzkkk
2023-09-17 13:18:13 +08:00
@colom
那你用 c 做什么东西吃饭?
底层 crud ?
zzzkkk
2023-09-17 23:44:45 +08:00
@yanqiyu
所以说 把那个++去掉就行 但留着++结果才正确 fsanitize 是不是报了假阳性
ngloom
2023-09-18 09:10:27 +08:00
@zzzkkk 哦哦, 还真是, 审题不清, 果然越来越菜了. T.T
weeei
2023-09-18 18:57:16 +08:00
是必须自己实现 strstr(' ') 吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/974127

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX