我目前正在学习c编程,但我处于一个非常基本的水平。因此,作为练习,我做了一个程序,读取一个字符串,并反转它。我想知道这些代码是否可读,以及如何改进它。
/*
* Goal: Given a string, invert it, then print the result.
* Author: Lúcio Cardoso
*/
#include <stdio.h>
#include <string.h>
/*This is the size of the arrays in this program. It's better to use a
constant, because makes easier to modify the arrays' size, if needed.*/
#define NUM 200
void invert(char *s) //Fucntion responsible for inverting the string.
{
char aux[NUM];
int i, j, n; //These variables are all used to control the for loops.
/*This loop will read the size of the array's string, that's why
strlen(s) - 1 is used. We don't need to read all contents
from the array, just the string. As we read the s[] backwards,
its content is stored in aux[n]. In this case, from zero to the
size of s[]'s string - 1. Minus 1 is used because we read it from ZERO,
not i. */
for (i = strlen(s) - 1, n = 0; n < strlen(s), i >= 0; i--, n++) {
aux[n] = s[i];
}
printf("Included with the super mojo from the string inverter, ");
printf("this is the result: ");
//This for loop reads all the content from the aux array, and print it.
for (j = 0; j < strlen(s); j++) {
printf("%c", aux[j]);
}
}
int main(void)
{
char string[NUM];
printf("\nWelcome to the super, duper string inverter!\n");
printf("If you want to see some magic, enter a string:\n>");
gets(string); //Reads the string.
//Now, we only need to call the function with string[] as a parameter.
invert(string);
return 0;
}发布于 2016-01-22 18:15:48
对于初学者来说,这是一个很好的小软件。以下是我的评论:
const**-修饰符**
由于不修改char *s的内容,所以可以安全地将函数签名更改为void invert(const char *s)。
太多的strlen()调用
您可以执行strlen(s)每个for-loop迭代。这对性能非常不利(特别是对于大型字符串),因为每次调用都会通过strlen循环整个字符串。如果您的字符串长度为100个字符(在NULL-character旁边),则结束于100*100 = 10000次迭代。
作为一种快速解决方案,您只需创建一个变量length并存储字符串的长度一次。从那时起,您将与length而不是strlen(x)进行比较,并将得到相同的结果(因为,s在执行时不会更改)。
比较未使用的n < strlen(s)在您的第一个for-loop中仍未使用。我认为您希望将这两种比较与&&联系起来:
for (i = strlen(s) - 1, n = 0; n < strlen(s) && i >= 0; i--, n++)为什么还要倒过来?
因为您的函数打印反向字符串,但不返回任何内容。你真的不需要逆转它。您可以从末尾开始循环输入字符串(就像在第一个循环中所做的那样),打印所有字符。如果返回指向该数组的指针以供以后使用,则额外的数组才有意义。
发布于 2016-01-22 20:54:31
你的功能不太灵活。如果另一段代码需要使用它,它将不得不将它用于一个单一的用途,并且这个目的是给出一个字符串,并以相反的顺序打印出该字符串。
以下是一些可以使其更加灵活的方法:
现在,反向字符串直接打印到STDOUT。为了使其更灵活,并使其遵循单一责任原则,您可以让函数接受一个输出缓冲区,将反向字符串插入:
void reverse(char *s, char *out) {这样,您还应该删除函数中的printf调用。
注意:一个更好的替代方案是覆盖原始字符串。与接受输出缓冲区不同,您可以在函数中创建一个临时输出缓冲区(就像使用aux一样)。然后,简单地将临时输出缓冲区复制到函数末尾的输入字符串中。正如200_success所说,
我确实建议把S作为一个输入输出参数,并将字符串反转到位.如果调用者想要保留原件的副本,那么他们可以自己先复制。将缓冲区分配的责任放在调用者身上可以减少C中内存管理方面的麻烦。
基本上,通过让输出转到输入字符串,内存管理就变得不那么复杂了,而且对调用者来说也更容易。
如果使用此函数的代码不希望反转整个字符串,怎么办?如果他们只想让字符串的第一部分反转呢?为了允许这样做,函数应该接受要反转的字符数量:
void reverse(char *s, char *out, size_t len) {然后,您只需在循环中使用len,就像您已经使用的那样。
够了;是时候回顾一下您已经提交的代码了。
对于(j = 0;j< strlen(s);j++) { printf("%c",auxJ);}
在这里,您正在循环遍历aux“数组”并打印出每个字符。然而,你把它复杂化了;为什么不直接打印aux呢?
printf("%s", aux);发布于 2016-01-23 00:18:57
printf打印单个char:printf("%c",auxJ);printf是一个非常方便的格式化输出的工具,但是它会带来相当大的开销--这不是您想要一次又一次调用的东西,没有一个很好的理由。将单个char打印到stdout的一个更有效的方法是: putchar(auxJ);或者,不需要遍历字符串逐个字符地打印它,只需使用一个函数调用就可以打印整个事件:put(Aux);(注意,puts会在字符串末尾再打印一个换行符。如果您想避免这种情况,请使用fputs(aux, stdout)。) puts和fputs要求字符串(aux)以NUL-字符('\0')结尾,而它不在您的程序中。如果要打印一个已知长度的字符序列(但可能没有这样的终止符字符),可以使用: fwrite(aux,1,strlen(n),stdout);puts或fputs打印程序中的所有字符串文字,并且开销更小,例如puts(“\n欢迎来到超级字符串转换器!”);而不是printf(“\n欢迎来到超级字符串转换器!\n”);现在您甚至不需要担心%字符被解释为格式描述符。https://codereview.stackexchange.com/questions/117608
复制相似问题