Trimmer de cadena primitiva en c -- beginner campo con algorithm campo con c campo con strings campo con array camp codereview Relacionados El problema

Primitive String trimmer in C


10
vote

problema

Español

Acabo de recoger C y estoy siguiendo a través de la c lenguaje de programación .

He tenido experiencia con muchos idiomas de nivel 'superior', por lo que cuando vi este ejercicio en el libro:

Escriba un programa para copiar su entrada a su salida, reemplazando cada cadena de uno o más espacios en blanco por un simple en blanco.

Pensé que creara un programa de ajuste muy básico y primitivo que toma una entrada y elimina todos los espacios blancos superfluos (más de 1 en una fila) e imprime una cadena 'recortada'.

Como se mencionó recientemente, recientemente, aún no hemos cubierto las matrices dinámicas, así que solo estoy usando las estáticas.

Pero esperaba obtener algunos comentarios sobre mi solución:

  #include <stdio.h>  /* ** A primitive trimmer ** to remove any superflous ** whitespaces in a given ** string (input). */  int main () {      /*     ** Setting up the variables     **     ** Working with static     ** arrays since I haven't     ** been introduced to dynamic.     */     char input [100], output[100];     fgets(input, 100, stdin);     int i = 0, k = 0;      // Looping over input until hitting     // an item containing a null-char.     while (input[i] != '') {         if (input[i] == ' ') { // hitting first space.             int j = i + 1;     // initiating temporary counter.             if (input[j] != '') {                                // find index of first non-space                                // character after initial space.                 while (input[j] != '' && input[j] == ' ') {                     if (input[j] == ' ') {                         i++; // keep indexing input-index                     }                     j++; // keep incrementing temporary indexer.                 }             }         }         output[k] = input[i]; // insert non-space item into output.         i++;                 // increment input-indexer.         k++;                 // prepare output-indexer for next non-space.     }     printf("%s", output);     // print trimmed input. }   

No va a ser bonita y es posible que no le guste, ¡pero tenga en cuenta que soy nuevo en el idioma!

Me gustaría obtener comentarios sobre mi solución general, cualquier opinión sobre el algoritmo de referencia y qué tan bien estoy siguiendo las mejores prácticas (sintácticas).

Original en ingles

I just picked up C and am following through The C programming language.

I've previously got experience with a lot of 'higher'-level languages, so when I saw this exercise in the book:

Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.

I thought I'd create a very basic and primitive trim-program that takes an input and removes all superfluous white-spaces (more than 1 in a row) and prints out a 'trimmed' string.

As mentioned I just recently started and we haven't covered dynamic arrays yet, so I'm just using static ones.

But I was hoping to get some feedback on my solution:

#include <stdio.h>  /* ** A primitive trimmer ** to remove any superflous ** whitespaces in a given ** string (input). */  int main () {      /*     ** Setting up the variables     **     ** Working with static     ** arrays since I haven't     ** been introduced to dynamic.     */     char input [100], output[100];     fgets(input, 100, stdin);     int i = 0, k = 0;      // Looping over input until hitting     // an item containing a null-char.     while (input[i] != '\0') {         if (input[i] == ' ') { // hitting first space.             int j = i + 1;     // initiating temporary counter.             if (input[j] != '\0') {                                // find index of first non-space                                // character after initial space.                 while (input[j] != '\0' && input[j] == ' ') {                     if (input[j] == ' ') {                         i++; // keep indexing input-index                     }                     j++; // keep incrementing temporary indexer.                 }             }         }         output[k] = input[i]; // insert non-space item into output.         i++;                 // increment input-indexer.         k++;                 // prepare output-indexer for next non-space.     }     printf("%s", output);     // print trimmed input. } 

It's not going to be pretty and you might not like it, but please keep in mind that I am new to the language!

I'd like to get feedback on my overall solution, any thoughts on the baseline algorithm and how well I'm following best (syntactical) practices.

              
   
   

Lista de respuestas

9
 
vote
vote
La mejor respuesta
 

INT vs size_t

en consecuencia al idioma C Especificación , es altamente recomendable usar < Código> protected void Dispose(bool disposing) { if (disposing) { IsDisposed = true; } Dispose(disposing); } 6 como el tipo para las variables de índice. Así que en su caso ...

  protected void Dispose(bool disposing) {     if (disposing) {         IsDisposed = true;     }     Dispose(disposing); }   7  

debe ser:

  protected void Dispose(bool disposing) {     if (disposing) {         IsDisposed = true;     }     Dispose(disposing); }   8  

protected void Dispose(bool disposing) { if (disposing) { IsDisposed = true; } Dispose(disposing); } 9 Condición Repetidos ReceiveData()0 Condición

Estaba un poco confundido por esta pieza de código

  ReceiveData()1  

Específicamente el ReceiveData()2 Condición: siempre será cierto debido al ReceiveData()3 lógica de condición. Entonces, como resultado, variable ReceiveData()4 duplica ReceiveData()5 con un invariante ReceiveData()6 .


Falta de carácter nulo

Si prueba su código en cualquier entrada de cadena, notará que el programa imprime algunos caracteres extraños después de su resultado. Sucede porque no copió el carácter ReceiveData()7 al ReceiveData()8 Array.


Tomando todo esto en una cuenta (así como las recomendaciones de @ Pacmaninbw's y @ Holroy)

  ReceiveData()9  
 

int vs size_t

Accordingly to the c language specification, it's highly recommendable to use size_t as the type for index variables. So in your case...

int i = 0, k = 0; 

should be:

size_t i = 0, k = 0; 

if condition repeats while condition

I was a bit confused by this piece of code

while (input[j] != '\0' && input[j] == ' ') {   if (input[j] == ' ') {     i++; // keep indexing input-index   }    j++; // keep incrementing temporary indexer. }  

Specifically the if condition - it will always be true due to the while condition logic. So, as result, variable j just duplicates i with an invariant j = i+1.


Lack of null character

If you test your code on any string input, you will notice that the program prints some strange characters after your result. It happens because you didn't copy the \0 character to the output array.


Taking all this into an account (as well as @pacmaninbw's and @holroy's recommendations)

#include <stdio.h> #include <ctype.h>  #define MAX 100  int main () {   char input [MAX], output[MAX];   fgets(input, MAX, stdin);   size_t inputIndex = 0, outputIndex = 0;    while (input[inputIndex] != '\0')     {          output[outputIndex++] = input[inputIndex];       if (input[inputIndex] == ' ')         while(input[++inputIndex] == ' ')           ;          else         inputIndex++;     }        output[outputIndex] = '\0';     printf("%s", output); } 
 
 
         
         
6
 
vote

Es un buen esfuerzo para principiantes, mantener el buen trabajo.

Este programa puede ser y probablemente debe ampliarse, solo procesará una sola línea de texto. Si bien el bucle que tiene en el programa debe trasladarse a una función que procesa una sola línea de texto, en el programa principal, debe tener un bucle que lea las líneas hasta que no haya más líneas. Una versión de GetChar () de este programa puede no tener esta limitación.

en lugar de comprobar específicamente para el espacio, debe incluir CTYPE.H

  #include <ctype.h>   

ha implementado muchas funciones como isspace () , isdigit()1 , 9988776655544332 , 99887766555443333 , islower() , toupper()5 y tolower() como macros. Esto debería ser más portátil que el cheque que tiene para ''.

             if (isspace(input[i]) { // hitting first space.   

use nombres de variables significativos

Es una mala práctica para usar los nombres de variables de carácter único. Uso de i , j4 , 99887766555443310 es un retroceso a Fortran que permitió las variables de enteros no declarados que comienzan con esas letras. El uso de nombres de variables significativos hace que el código sea más fácil de leer, comprender y depurar. También reduce la cantidad de comentarios necesarios.

Algunos ejemplos pueden ser:

  isdigit()1  

Es un mal hábito declarar todas las variables en una línea. Cada variable debe estar en su propia línea para facilitar la búsqueda de la declaración.

Si ha leído el capítulo en variables de puntero, es posible que desee usar

  isdigit()2  

es más eficiente que usar la entrada [InputIndex];

use constantes simbólicas en lugar de números

En C puede definir constantes simbólicas utilizando la Directiva isdigit()3 Processor.

  isdigit()4  

Hay varios beneficios para esto:

  1. Primero, puede cambiar fácilmente el tamaño de la matriz cambiando el código en un solo lugar.
  2. hace que el código sea más legible.
  3. Si se usa un bucle para la misma constante se puede usar en el bucle para asegurarse de que las matrices no se indexan más allá del tamaño de la matriz.

Dado el código actual que no puede salir del extremo de la matriz porque 99887766555443315 Termina una línea de código con isdigit()6 , que puede no ser siempre el caso. La indexación más allá del final de la matriz puede producir resultados desconocidos. Una versión ligeramente más segura del bucle while es

  isdigit()7  

Es posible que el número mágico (constante numérico en lugar de constante simbólico) 100 sea una mala elección. La memoria se asigna por tamaño de palabra que siempre va a ser una potencia de 2. Dependiendo de la computadora, esto puede ser de 4 bytes u 8 bytes (4 caracteres u 8 caracteres). No es crítico en este caso particular, pero si la matriz está dentro de una estructura, podría afectar la asignación de la memoria.

 

It's a nice beginner effort, keep up the good work.

This program can be and probably should be expanded, it will only process a single line of text. The while loop you have in the program should be moved into a function that processes a single line of text, in the main program you should have a loop that reads lines until there are no more lines. A getchar() version of this program may not have this limitation.

Rather than checking specifically for space, you should include ctype.h

#include <ctype.h> 

It has implemented a lot of functions such as isspace(), isdigit(), isalnum(), isupper(), islower(), toupper(), and tolower() as macros. This should be more portable than that the check you have for ' '.

           if (isspace(input[i]) { // hitting first space. 

Use Meaningful Variable Names

It's a bad practice to use single character variable names. using i, j, k etc. is a throwback to Fortran that allowed undeclared integer variables starting with those letters. Using meaningful variable names makes the code easier to read, understand and debug. It also reduces the number of comments necessary.

Some examples might be:

int inputIndex = 0; int outputIndex = 0; 

It's a bad habit to declare all of the variables on one line. Each variable should be on it's own line to make it easier to find the declaration.

If you have read the chapter on pointer variables you might want to use

char *inputCharacterP; char *outputCharacterP; 

It is more efficient than using input[inputIndex];

Use Symbolic Constants Rather Than Numbers

In C you can define symbolic constants using the #define pre-processor directive.

#define IO_CHARACTER_ARRAY_SIZE 100 int main() {     char input[IO_CHARACTER_ARRAY_SIZE];     char output[IO_CHARACTER_ARRAY_SIZE]; 

There are multiple benefits to this:

  1. First you can easily change the size of the array by changing the code in only one place.
  2. It makes the code more readable.
  3. If a for loop is used the same constant can be used in the for loop to make sure that arrays aren't indexed past the size of the array.

Given the current code you can't walk off the end of the array because fgets() terminates a line of code with '\0', that may not always be the case. Indexing past the end of the array can produce unknown results. A slightly safer version of the while loop is

    while ((inputindex < IO_CHARACTER_ARRAY_SIZE) && (input[inputIndex] != '\0')) {     } 

It's possible that the magic number (numerical constant rather than symbolic constant) 100 is a bad choice. Memory is allocated by word size which is always going to be a power of 2. Depending on the computer this can be either 4 bytes or 8 bytes (4 chars or 8 chars). It's not critical in this particular instance, but if the array is within a struct it could affect memory allocation.

 
 
     
     
6
 
vote

Las respuestas de PGS y PacmaninBW tienen sus buenos puntos con respecto al estilo del código y la emisión con su código, por lo que voy a dar seguimiento al "Posible problema duplicado" y su declaración: "Cualquier opinión sobre el algoritmo de referencia y cómo Bueno, estoy siguiendo las mejores prácticas (sintácticas) ".

Al leer el objetivo de ejercicio y su implementación, pensé en dos principios comunes aplicados a la programación: la beso principio, y Razor de Occam . Su código se basa en la obtención del objetivo del ejercicio, e implementa cosas que no son requeridas por el objetivo. En general, esto es algo que uno como programador debe intentar evitar. (NB! Voy a ver que es interesante como una experiencia de aprendizaje, pero se sorprenderá de ver cuántas soluciones de código excesivamente existen en el mundo real)

En primer lugar, su solución agrega efectos secundarios al objetivo original. Su solución reembolsa una línea a terminar, antes de emitir algo. Si escribe menos de un 100 caracteres, o no lo termine con retorno / cambio de línea, no emitirá nada.

En segundo lugar, aunque no es mucho, su código requiere más memoria de la que se expresa la meta. Como muestra la otra (pregunta duplicada), casi no es necesario almacenar nada, además de la lectura de carácter actual, y una variable de bandera para indicar si el carácter anterior fue un espacio o no. Su código requiere dos matrices de 100 bytes y varios caracteres en bucle. Si esto hubiera estado en un dispositivo restringido de memoria, habría sido catastrófico.

En tercer lugar, agregando / cambiando objetivos, agrega / elimina las características. En su caso, limita la entrada / salida a 100 caracteres al no tener un bucle de rentas alrededor del 9988776665544330 , e introduce un posible caso relacionado con el lavado de búferes de salida usando printf() < / Código>.

( y si recuerdo correctamente, si realmente es realmente desafortunado, podría obtener problemas combinando fgets() y printf()3 que utiliza diferentes llamadas del sistema para leer y escritura. Lo más probable es que no sea un problema en su caso, a medida que usa una para la entrada y otra para la salida ... Si sin embargo, usaría 9988776655544334 y 9988776655544335 , o fgets() y scanf() Al mismo tiempo, podría terminar en un montón de problemas. )

Para resumir, la sobrecarga de una solución o extenderla más allá de la meta podría ser algo malo que hacer. En su caso, con fines de aprendizaje, puede aprenderle algo más. Sin embargo, luego habría extendido la meta de antemano, y enfatizaría por qué lo ha extendido y lo que son sus nuevos objetivos. Por ejemplo, para leer línea por línea eliminando espacios adicionales para un manejo más rápido de escenarios de entrada más grandes .

Déjame terminar diciendo que, en general, su código se ve bien con la sangría adecuada y un buen estilo de abrazadera. Tal vez un poco de comentarios sobre cosas obvias, pero también algunos comentarios buenos y vitales a lo que sucede en su código.

 

The answers by pgs and pacmaninbw has their good points regarding code style and issue with your code, so I'm going to follow up on the "possible duplicate issue" and your statement: "any thoughts on the baseline algorithm and how well I'm following best (syntactical) practices."

When reading the exercise goal and your implementation I thought of two common principles applied to programming: the KISS principle, and Occam's Razor. Your code is overcomplicating the exercise goal, and implements stuff which are not required by the goal. In general, this is something one as a programmer should try to avoid. (NB! I do see that it is interesting as a learning experience, but you'd be surprised to see how many overengineered code solutions there exists in the real world)

First of all, your solution adds side effects to the original goal. Your solution reequires a line to be ended, before outputting anything. If you type less than a 100 characters, or don't end it with return/line shift, it won't output anything.

Secondly, although not a lot, your code requires more memory than the goal expresses. As the other (somewhat duplicated question) shows, there is almost no need to store anything besides the current character read, and a flag variable to indicate whether previous character was a space or not. Your code requires two 100 byte arrays and several looping characters. If this had been on a memory restricted device, it would have been catastrophic.

Thirdly, by adding/changing goals, you add/remove features. In your case, you limit the input/output to a 100 characters by not having a while loop around the fgets(), and you introduce a possible case related to flushing of output buffers by using printf().

(And if I remember correctly, if you're really unlucky you could get issues by combining fgets() and printf() which uses different system calls for reading and writing. Most likely not an issue in your case, as you use one for input and one for output... If however, you'd use fputs() and printf(), or fgets() and scanf() at the same time, you could end up on a heap of trouble.)

So to summarize, overengineering a solution or extending it beyond the goal could be a bad thing to do. In your case, for learning purposes, it can learn you something else. I would however then have extended the goal beforehand, and emphasize why you've extended it and what your new goals are. For example, to read line by line stripping away extra spaces for a faster handling of larger input scenarios.

Let me finish off by saying, that in general your code does look good with proper indentation and a good brace style. Maybe a little too much commenting on obvious stuff, but also some good and vital comments to what happens where in your code.

 
 
   
   
3
 
vote

Omitir la comprobación si el carácter de entrada es un espacio, en su lugar, verifique si no es un espacio, si es así, agregarlo a la salida y el incremento k. Este método también le permitiría hacer este ajuste en su lugar, lo que le permite eliminar que debe usar el tampón de salida (si se desea).

NOTA No creo que este es un adorno verdadero, ya que todavía tendrá al menos un espacio al principio y al final, creo que el recorte eliminaría todos los espacios anteriores y posteriores.

  int i=0,k=0;  while (input[i])  {    // Add char if its not a space, or it can be anything if its the first,    // or if at least one char is in the output and the last is not a space    if ((input[i]!=' ')||(!k)||(k&&output[k-1]!=' ')) output[k++]=input[i];    i++; } // Dont forget to terminate output output[k]=0;   
 

Skip checking if the input character is a space, instead check if it is NOT a space, if so, add it to the output and increment k. This method would also allow you to do this trim in place, allowing you to drop having to use the output buffer (if desired).

Note I do not think this is a true trim, since you will still have at least one space at the start and end, I believe trim would remove all preceding and trailing spaces.

int i=0,k=0;  while (input[i])  {    // Add char if its not a space, or it can be anything if its the first,    // or if at least one char is in the output and the last is not a space    if ((input[i]!=' ')||(!k)||(k&&output[k-1]!=' ')) output[k++]=input[i];    i++; } // Dont forget to terminate output output[k]=0; 
 
 
   
   
2
 
vote

Su código como escrito

  • no rompe el problema en funciones. Eso es solo mala política.
  • utiliza, sin razón, indexación de matriz. La indexación de la matriz está bien si lo necesita, pero no lo hace aquí. Solo necesita escanear la entrada una vez. Use puntero aritmético en su lugar. Es más rápido y más legible.
  • encarna un algoritmo complicado. Debe una máquina de estado simple de dos estados. En cada punto, usted está "comiendo" espacio en blanco, o de lo contrario, no.

Aquí hay una versión mejorada (sin el archivo E / S):

  int isspace(c) {   return c == ' '; }  void condense(char *d, const char *s) {   int eating = 0;   char c;   while ((c = *s++)) {     if (eating) {       if (!isspace(c)) {         *d++ = c;         eating = 0;       }     } else {       *d++ = c;       eating = isspace(c);     }   }   *d = 0; }   

Esto ciertamente podría y debe mejorarse, pero es un comienzo.

"Hay dos formas de construir una pieza de software: uno es hacerlo tan simple que obviamente no haya errores, y el otro es hacerlo tan complicado que no haya errores obvios".
- Tony Hoare

 

Your code as written

  • does not break the problem up into functions. That's just bad policy.
  • uses, without reason, array-indexing. Array-indexing is fine if you need it, but you don't here. You only need to scan through the input once. Use pointer arithmetic instead. It's faster and more readable.
  • embodies a complicated algorithm. It should a simple two-state state machine. At each point, you are either "eating" white-space, or else you're not.

Here is an improved version (without the file I/O):

int isspace(c) {   return c == ' '; }  void condense(char *d, const char *s) {   int eating = 0;   char c;   while ((c = *s++)) {     if (eating) {       if (!isspace(c)) {         *d++ = c;         eating = 0;       }     } else {       *d++ = c;       eating = isspace(c);     }   }   *d = 0; } 

This certainly could and should be improved, but it's a start.

xe2x80x9cThere are two ways of constructing a piece of software: One is to make it so simple that there are obviously no errors, and the other is to make it so complicated that there are no obvious errors.xe2x80x9d
xe2x80x95 Tony Hoare

 
 
 
 
1
 
vote

Voy a revisar toda su línea de programas por línea:

  char input [100], output[100]; fgets(input, 100, stdin); int i = 0, k = 0;   

En primer lugar, no sé si está apuntando a la conformidad estándar, pero debo decir que las declaraciones y el código de mezcla son ilegales en C90 (lo llamado "ANSI C", aunque los estándares posteriores fueron creados por ANSI también). Cambiar el orden de líneas como este lo hará compatible con C90:

  char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin);   

En segundo lugar, desde el principio puedo ver que su programa no puede manejar más de cien caracteres. Arrays locales (evitaría llamarlos estática, es posible que no sepa sobre esto, pero hay una palabra clave 998877765555544332 que puede preceder a una declaración de una variable y cambia su comportamiento drásticamente) en realidad es un buen comportamiento). Elección Para este tipo de problema, solo tiene que usar un bucle para tomar datos en lotes. También me gustaría señalar que fgets se detiene cuando lee un carácter de nueva línea y supongo que esta no fue su intención, porque en la descripción del problema, nunca dices "línea" una vez , solo "entrada". Definir cualquier constancia que utilice es una buena práctica y facilita la cambiarlos más tarde. Reemplacé printf("%s", output) con fputs(output, stdout) , porque creo que es un poco más legible. Resumiendo, estructuraría el código como este:

  #define BUF_LEN     100  int main() {     int i, k;     char input[BUF_LEN], output[BUF_LEN];      while(!feof(stdin)) /* until we reach the end of stdin */     {         i = k = 0;         fgets(input, BUF_LEN, stdin); /* read the next batch of data */          ...          fputs(output, stdout); /* print output for the current batch of data */     } }   

ahora en cuanto al algoritmo real:

  while (input[i] != '') {     if (input[i] == ' ') { // hitting first space.         int j = i + 1;     // initiating temporary counter.         if (input[j] != '') {                            // find index of first non-space                            // character after initial space.             while (input[j] != '' && input[j] == ' ') {                 if (input[j] == ' ') {                     i++; // keep indexing input-index                 }                 j++; // keep incrementing temporary indexer.             }         }     }     output[k] = input[i]; // insert non-space item into output.     i++;                 // increment input-indexer.     k++;                 // prepare output-indexer for next non-space. }   

C ++ Style // Los comentarios también son ilegales en C90. A menudo, compruebe si el carácter actual no es '' , y luego prueba si es igual a espacio después. Un carácter no puede ser char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 0 y char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 1 al mismo tiempo, por lo que la primera verificación es innecesaria. Me gusta verificar el carácter nulo simplemente probando la variable en sí (verá lo que quiero decir en la muestra a continuación), pero eso es solo una preferencia. Puede reemplazarlo mientras se bucea con un bucle para hacerlo más legible. Lo último es que a menudo no necesita usar la variable como un índice y incrementarlo por separado, porque el operador posterior a incremento le dará el valor actual al mismo tiempo que incrementará la variable por uno. Según lo señalado por otros, debe terminar char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 2 con un carácter nulo. El resultado final es esto:

  char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 3  

Con respecto al rendimiento, hice referencia a esta versión y el más simple que usa solo GetChar y Putchar con char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 4 . Escribí otro programa que imprime los datos aleatorios con espaciado, conectélo al programa de referencia a través de una tubería y luego redirige la salida completa a char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 5 . Esta versión fue aproximadamente tres veces más rápido, aunque usé un búfer de 4096 bytes. Dado que al final, casi no es más difícil de implementar, parece una mejor manera de abordar este problema.

 

I'll go over your entire program line by line:

char input [100], output[100]; fgets(input, 100, stdin); int i = 0, k = 0; 

First of all, I don't know if you're aiming for standard conformity, but I must say that mixing declarations and code is illegal in C90 (so called "ANSI C", even though later standards were created by ANSI too). Changing the order of lines like this will make it C90-compliant:

char input [100], output[100]; int i = 0, k = 0; fgets(input, 100, stdin); 

Secondly, right from the beginning I can see that your program can't handle more than one hundred characters. Local arrays (I'd avoid calling them static, you might not know about this yet, but there is a static keyword which can precede a declaration of a variable and changes it's behavior drastically) are actually a good choice for this type of problem, you just have to use a loop to take data in batches. I'd also like to point out that fgets stops when it reads a newline character and I'm guessing this wasn't your intention, because in the description of the problem you never say "line" once, only "input." Defining any constants you use is a good practice and makes it easy to change them later. I replaced printf("%s", output) with fputs(output, stdout), because I think it's slightly more readable. Summing up, I'd structure the code like this:

#define BUF_LEN     100  int main() {     int i, k;     char input[BUF_LEN], output[BUF_LEN];      while(!feof(stdin)) /* until we reach the end of stdin */     {         i = k = 0;         fgets(input, BUF_LEN, stdin); /* read the next batch of data */          ...          fputs(output, stdout); /* print output for the current batch of data */     } } 

Now as for the actual algorithm:

while (input[i] != '\0') {     if (input[i] == ' ') { // hitting first space.         int j = i + 1;     // initiating temporary counter.         if (input[j] != '\0') {                            // find index of first non-space                            // character after initial space.             while (input[j] != '\0' && input[j] == ' ') {                 if (input[j] == ' ') {                     i++; // keep indexing input-index                 }                 j++; // keep incrementing temporary indexer.             }         }     }     output[k] = input[i]; // insert non-space item into output.     i++;                 // increment input-indexer.     k++;                 // prepare output-indexer for next non-space. } 

C++ style // comments are also illegal in C90. You often check if the current character is not '\0', and then test if it equals space right afterwards. A character cannot be '\0' and ' ' at the same time, so the first check is unnecessary. I like checking for null character by simply testing the variable itself (you'll see what I mean in the sample below), but that's just a preference. You can replace while loops with a for loop to make it more readable. The last thing is that you often don't need to use variable as an index and increment it separately, because post-increment operator will give you the current value while also incrementing the variable by one. As pointed out by others, you need to terminate output with a null character. The end result is this:

while (input[i]) {     /* input[i] instead of input[i] != '\0' */     if (input[i] == ' ')         for (j = i + 1; input[j] == ' '; j++) /* compressed the next few lines into this for loop */             i++;     /* I removed brackets to make the code more compact,       * but that's just a matter of preference */     output[k++] = input[i++]; } output[k] = '\0'; 

Regarding the performance, I benchmarked both this version and the simpler one which uses only getchar and putchar with /usr/bin/time. I wrote another program that prints out random data with spacing, connected it to the benchmarked program through a pipe and then redirected entire output to /dev/null. This version was about three times faster, though I used a buffer of 4096 bytes. Since in the end it's hardly more difficult to implement, it seems like a better way to approach this problem.

 
 
 
 

Relacionados problema

2  Devuelve verdadero si los elementos de una matriz no contienen uno u otro  ( Return true if the elements of an array do not contain one or the other ) 
Estoy completando gradualmente los ejercicios de codificación para Java. Aquí está el uno acabo de hacer: Dada una matriz de INTS, devuelva verdadera si ...

2  Cargando imágenes en el fondo para una vista de tabla  ( Loading images in the background for a table view ) 
Tengo fetchData2 MÉTODO QUE LLENA MI imagesArray : func fetchData(){ let imageQuery = PFUser.query() imageQuery?.whereKey("username", contained...

6  Buscar número de más en una matriz 2D  ( Find number of plus in a 2d array ) 
Problema Chargrid El CharGrid La clase encapsula una matriz de 2-D con una pareja de operaciones. INT APULUS () Busque un patrón '+' en la cuadrícu...

6  Palindrome más largo en una matriz  ( Longest palindrome in an array ) 
Soy nuevo en la programación, y creo que este código podría mejorarse. ¿Alguna sugerencia? 'done'0 ...

2  Importando datos en Excel  ( Importing data into excel ) 
¿Existe una forma más fácil de importar datos en una matriz de Excel u otra estructura de datos? He intentado investigar colecciones, pero he encontrado la D...

6  Clase de matriz multidimensional simple en C ++ 11  ( Simple multi dimensional array class in c11 ) 
La nueva versión del código se puede revisar en Clase de matriz multidimensional simple en C ++ 11 - Seguimiento . El siguiente código implementa una clas...

7  Colecciones vacías en caché  ( Cached empty collections ) 
A menudo necesito devolver las colecciones vacías. Uno de esos días, escribí lo siguiente para devolver una instancia en caché: public static class Array<...

5  Encuentra el primer número único de la matriz  ( Find first unique number from array ) 
Se me pidió que creara una función que devuelva el primer entero único de la matriz de enteros. En un caso de éxito, la función devuelve el número único en un...

6  Fusionando dos varias de clases  ( Merging two array of classes ) 
Tengo esta función que debe fusionar dos matriz de clases cuando id es igual a id de Array2. Para la simplicidad, convirtí una matriz en un arraylist pa...

2  Mejora de la función que compara dos cadenas  ( Improving function that compares two strings ) 
Estoy aprendiendo C y he hecho esta función muy simple para comparar dos cuerdas. Me gustaría saber cómo se puede mejorar: int match(char* string1, char* s...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos