我正在尝试在C中反转字符串。反向函数只是将给定位置(在for循环中)的字符分配给临时对象。我在程序中看不到任何逻辑错误,程序在gcc 4.7.2下使用以下命令成功编译:
gcc -Wall -std=c99 reverse.c
要重新创建问题:
1。)运行程序并在shell中输入一个字符串
2.完成输入后,按enter /和/或您的EOF信号。
问题是既没有打印原始字符串,也没有反转字符串。这也是K& R第二版的练习,如果你完成了这个练习,我将不胜感激。
我认为该错误是由缺少空字符引起的,着名的printf需要一个以空字符结尾的字符串来打印输入到cin。 getline函数将一个空字符分配给数组的末尾,当然空字符将是字符串中结束printf的第一个字符(因此不会打印字符/文字)。
#include <stdio.h>
#define MAXLINE 1000
int geline(char s[], int lim);
void reverse(char line[], int length);
int main()
{
char s[MAXLINE];
char t[MAXLINE];
int k, len;
while ((len = getline(s, MAXLINE)) > 0) {
if (len > 1)
reverse(s, len);
}
printf("%s", s);
return 0;
}
void reverse (char input[], int length)
{
char temp[MAXLINE];
int j = length;
for (int i = 0; i < length; ++i, --j) {
temp[i] = input[i];
input[i] = input[j];
input[j] = temp;
}
}
int getline(char s[], int lim)
{
int c, i;
for (i=0; (c=getchar()) != EOF && c!='\n'; ++i)
s[i] = c;
if (c== '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
答案 0 :(得分:2)
有两个逻辑错误:
int j = length;
应为int j = length - 1;
temp[i] = input[i] ... input[j] = temp;
最后一个错误有两种方法:
temp
定义为单个字符:char temp; ... temp = input[i]; input[i] = input[j]; input[j] = temp;
temp
:temp[i] = input[i]; input[i] = input[j]; input[j] = temp[i]
试试这段代码:
#include <stdio.h>
#define MAXLINE 1000
int geline(char s[], int lim);
void reverse(char line[], int length);
int main () {
char s[MAXLINE];
char t[MAXLINE];
int k, len;
while ((len = getline(s, MAXLINE)) > 0) {
if (len > 1)
reverse(s, len);
}
printf("%s", s);
return 0;
}
void reverse (char input[], int length) {
char temp;
int j = length - 1;
for (int i = 0; i < j; ++i, --j) {
temp = input[i];
input[i] = input[j];
input[j] = temp;
}
}
int getline (char s[], int lim) {
int c, i;
for (i=0; (c=getchar()) != EOF && c!='\n'; ++i)
s[i] = c;
if (c== '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
答案 1 :(得分:1)
int j = length - 1; // Thanks to @chux
for (int i = 0; i < j; ++i, --j) { // or <= length / 2
char temp = input[i];
input[i] = input[j];
input[j] = temp;
不需要temp,也没有完全正确使用。
您要两次交换值,这会在循环的后半部分恢复交换。 :)
你的原型错过了't'(geline
)。因此可能
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
是的?
答案 2 :(得分:1)
你可以使用这个快速功能:
inline char * reverse(char *p)
{
char *save=p;
char *q = p;
while(q && *q) ++q;
for(--q; p < q; ++p, --q)
*p = *p ^ *q,
*q = *p ^ *q,
*p = *p ^ *q;
return save ;
}
答案 3 :(得分:1)
(我使用-Wall -std=c99 -O3 -g
编译,-g
允许使用gdb
)
以下是我注意到的事情以及解决这些问题的一些方法。我试图密切关注你开始的样式(例如,我会将原型中的数组decls转换为指针,但这不是必需的。)
您的getline
原型错过了t
。
int getline(char s[], int lim);
在main
中,您实际上并不需要k
,t[MAXLINE]
,并且您的printf
可能应该在循环中,因此您会看到每个单词都是逆转。请注意,printf
会选择\n
,因为下面的getline
会将换行和EOF终止的行转换为相同的内容(没有换行符):
int main()
{
char s[MAXLINE];
int len;
while ((len = getline(s, MAXLINE)) > 0) {
if (len > 0)
reverse(s, len);
printf("%s\n", s);
}
return 0;
}
在上面,getline(s, MAXLINE)
本来可能是getline(s, sizeof(s) / sizeof(*s) - 1)
,但是请注意fencepost错误(请注意- 1
)。
reverse
函数可以大大改进,而不必考虑xor的疯狂跳过变量(尽管Daffra的例子很有趣,特别是它正确地在中间停止)。相反,拥有只是指向中途点的感觉是明显的胜利。在此之间删除temp
数组只是一个临时字符,保留了你的一般风格。
void reverse (char input[], int length)
{
int max = length - 1; /* keep the final NUL in place */
for (int i = 0; i <= max / 2; ++i) {
char ch = input[i];
input[i] = input[max - i];
input[max - i] = ch;
}
}
在上面的gcc -O3
中可以对代码进行严格的修改,因此没有理由担心在每次循环测试等时都会执行长除法。例如,gdb
报告i
本身会自动优化,这非常有趣。首先编写好的,可读的代码,对编译器有一定的信心,稍后进行优化。
最后,getline
受益于针对lim
(CRITICAL!)的测试以及将换行符转换为NUL。
int getline(char s[], int lim)
{
int i, c;
for (i=0; (i <= lim) && ((c=getchar()) != EOF) && (c != '\n'); ++i)
s[i] = c;
s[i] = '\0';
return i; /* return the index to the final NUL, same as length w/o it */
}
将MAXLINE
设置为10会暂时显示此版本相当优雅地处理超长行,将它们分成两个单独的行,而不会丢失任何字符。
小心使用字符串以非常清楚地决定是要根据长度来描述它们,还是根据最后的NUL索引来描述它们。这会影响你如何表达你的循环,限制,变量名等,显然混淆它们是fencepost错误的经典来源。
希望这有帮助。
答案 4 :(得分:0)
请看一下这段代码:
#include <stdio.h>
#define MAXLINE 1000
int geline(char s[], int lim);
void reverse(char line[], int length);
int main()
{
char s[MAXLINE];
int len;
while ((len = geline(s, MAXLINE)) > 1) {
if (len > 1) {
reverse(s, len);
printf("%s", s);
}
}
return 0;
}
void reverse (char input[], int length)
{
char temp;
int j = length-1;
for (int i = 0; i < j; ++i, --j) {
temp = input[i];
input[i] = input[j];
input[j] = temp;
}
}
int geline(char s[], int lim)
{
int c, i;
for (i=0; (c=getchar()) != EOF && c!='\n'; ++i)
s[i] = c;
if (c== '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
答案 5 :(得分:0)
这里只需要进行2次更改,并且反之亦然。 内部功能反向只需执行此操作
int j = --length;
而不是:
input[j] = temp; //you should use
input[j] = temp[i];