elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Entrar al Canal Oficial Telegram de elhacker.net


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [C] ¿Qué hace este while de una sola linea?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [C] ¿Qué hace este while de una sola linea?  (Leído 3,084 veces)
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
[C] ¿Qué hace este while de una sola linea?
« en: 25 Noviembre 2015, 01:31 am »

Código
  1. #include <stdio.h>
  2.  
  3. int main (void){
  4.  
  5.  int a,c;
  6.  a=c=3;
  7.  
  8.  while ((a=c=getchar()) == '1');
  9.  
  10.  printf ("c:%c\n",c);
  11.  printf ("a:%c\n",a);
  12.  
  13.  return 0;
  14. }


Código:
[dresuer@emachine TRABAJILLO]$ echo '3' | ./TEST
c:3
a:3
[dresuer@emachine TRABAJILLO]$ echo '1' | ./TEST
c:

a:

[dresuer@emachine TRABAJILLO]$

¿Qué hace este programa?

¿Por qué a y c valen una nueva linea?

¿a=c='\n'?

No entiendo.


En línea

LET'S DO STUFF!!
class_OpenGL


Desconectado Desconectado

Mensajes: 437

Si usas Direct3D, no eres mi amigo :P


Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #1 en: 25 Noviembre 2015, 02:53 am »

Lo que hace getchar, como dice su nombre, es tomar un byte del buffer stdin. Cuando tu introduces un carácter en la consola, se guarda ese carácter Y un salto de línea. Entonces, getchar toma ese carácter introducido y deja el salto de línea sin eliminar. Entonces, esta es la secuencia:

1º Introducimos un 1 por consola y le damos a enter para seguir. En el buffer de stdin se guarda la siguiente secuencia: 0x310A (31 es '1' en hexadecimal y 0A es un salto de línea).
2º Getchar toma el primer byte de esa secuencia (31).
3º Como La condición 31 == '1' se cumple, entonces el la sentencia while se ejecuta (en este caso, la sentencia es nula)
4º Comparamos de nuevo. Como en el buffer de stdin aún hay datos, entonces el programa no se pausa, sino que toma datos de esa secuencia. En este caso, getchar retorna 0x0A, lo que es un salto de línea. Como 0x0A es distinto de '1', entonces el while ya no se ejecuta y las variables a y c se quedan con el valor de salto de línea (0x0A).

Conclusiones:
-Si introducimos un '1', entonces las variables a y c guardarán un salto de línea.
-Si ponemos cualquier otro carácter, las variables a y c guardarán ese carácter y el buffer de stdin se quedará con un elemento por leer.


En línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #2 en: 25 Noviembre 2015, 04:34 am »

Me parece muy confusa tu forma de explicar.

Todavía no lo entiendo bien, o sea yo creía que solo cuando se daba la igualdad no se hacía la asignación algo así

¿Podrías explicarmelo de nuevo, con otras palabras?

Saludos!
En línea

LET'S DO STUFF!!
class_OpenGL


Desconectado Desconectado

Mensajes: 437

Si usas Direct3D, no eres mi amigo :P


Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #3 en: 25 Noviembre 2015, 05:13 am »

Antes de nada, quiero dejar una nota aclaratoria. El sistema operativo tiene un buffer (espacio de memoria) para los valores de entrada de una consola. En C y C++, podemos acceder indirectamente a este buffer como si de un archivo se tratara.

Definición de stdin según cplusplus:
Código
  1. FILE * stdin;
(Puede diferir entre compiladores)

Para más información, consulta: esta página
__________________________________________

Aunque la sentencia "a=c=getchar()" esté dentro de la condición del while, la igualación se hace igual. Es como si hicieras:
Código
  1. a = c= getchar();
  2. while(a == '1') { // a y c tienen el mismo valor, puedes poner la que quieras
  3.    a = c = getchar();
  4. }
Que a su vez, equivale a
Código
  1. a = getchar();
  2. c = a;
  3. while(a == '1') { // a y c tienen el mismo valor, puedes poner la que quieras
  4.    a = getchar();
  5.    c = a;
  6. }

Vamos a analizar este segundo código:

-Primero, tienes que saber que en las operaciones de igualdad se ejecutan de derecha a izquierda, por lo que primero se ejecuta la función getchar() y posteriormente el valor de retorno se le asigna a la variable 'a'.
Cuando ejecutas esta función, si el buffer que maneja stdin no tiene datos (ese buffer lo guarda el sistema operativo, no tenemos acceso a el directamente) entonces el programa se pausa y espera a que el usuario introduzca datos. Cuando introducimos datos, al final tenemos que pulsar enter, y ese enter se guarda (es decir, se guarda el salto de línea). Por ejemplo, si introducimos un '1' y le damos a enter, se va a guardar la siguiente secuencia de bytes: 0x31 (equivale a '1') y 0x0A (equivale a 'salto de línea' o '\n'). Entonces, la función getchar va a tomar el primer byte que se encuentra. En este caso, va a ser el 0x31. Los datos obtenidos se borran del buffer de stdin, por lo que ahora este buffer tiene solamente el salto de línea (0x0A)

-Segundo, igualamos a la variable c el valor de a, es decir, a partir de esa sentencia, a y c tienen exactamente el mismo valor (si seguimos el ejemplo anterior, a y c valen '1').

-Tercero, en el while, comprobamos si el usuario ha introducido un '1'. De ser así, el while ejecutaría el bloque de sentencias del while. Como en este ejemplo sí que hemos introducido un '1', entonces el while se ejecutará. Al ejecutarse el while, llamamos a la función getchar() de nuevo. Como ya he dicho, getchar toma datos del buffer de stdin. En este caso, este buffer SI tiene datos, por lo que el programa NO se va a pausar de nuevo. Entonces, los datos que hay son un salto de línea (como vimos en el paso 1), por lo que getchar toma ese salto de línea, borra ese dato del buffer de stdin y se lo asigna a la variable 'a'. Entonces, ahora la variable 'a' tiene el valor de un salto de línea.

-Cuarto, le asignamos el valor de 'a' a la variable 'c'.

Por todo esto, las variables 'a' y 'c' equivalen a un salto de línea cuando introduces un '1'.
« Última modificación: 25 Noviembre 2015, 05:16 am por class_OpenGL » En línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #4 en: 25 Noviembre 2015, 05:45 am »

Bueno, sí entendí mejor por lo menos la idea.

Ahora si yo quisiera por ejemplo escribir esto pero sin un while ¿Cómo lo haría?

Código
  1. while ((buffer[0] = c = getchar()) == ' ' || c == '\t' || c=='\n');

O sea yo en realidad todavía no entiendo que hace ese while cuando se cumple la condición y si no se cumple.

 :-\

Saludos!
« Última modificación: 25 Noviembre 2015, 05:50 am por nisteeklod » En línea

LET'S DO STUFF!!
class_OpenGL


Desconectado Desconectado

Mensajes: 437

Si usas Direct3D, no eres mi amigo :P


Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #5 en: 25 Noviembre 2015, 05:51 am »

No entiendo cuál era el objetivo final de este código. Con esa información, podríamos ayudarte mejor y con respuestas más claras.

Tienes que saber que esas operaciones  son binarias, es decir, se involucran dos "cosas". Por ejemplo, el operador = es binario puesto que necesita dos cosas: una variable a la que asignar un valor, y el dicho valor (a = b, se necesita tanto "a" como "b"). Pero te preguntarás: ¿qué pasa con la sentencia a = 5 + 1 + 3 * 5 - 7? Pues bien, esa operación, a la hora de compilar, se divide en operaciones de dos en dos. Normalmente, el orden de preferencia va de izquierda a derecha, pero con el operador = va de derecha a izquierda. Vamos a expresar la sentencia que he puesto de ejemplo en operaciones binarias:

1º Está el operador =, por lo que es de derecha a izquierda. Primero tenemos que procesar 5 + 1 + 3 * 5 - 7.
2º El operador * tiene preferencia sobre los operadores + y -, por lo que en primer lugar se procesa 3 * 5. Una vez procesado, quedaría así:
5 + 1 + 15 - 7
3º Como entre los operadores + y - no hay preferencia, la expresión se evalua de izquierda a derecha:
>> 6 + 15 - 7
>> 21 - 7
>> 14
4º La expresión final quedaría así:
a = 14
Por tanto, a la variable a se le asigna el valor 14.

Para saber más sobre la preferencia entre operadores, consulta : esta página

Una vez sabido esto, puedes analizar la expresión que tienes en tu while
« Última modificación: 25 Noviembre 2015, 06:12 am por class_OpenGL » En línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #6 en: 25 Noviembre 2015, 06:12 am »

Código
  1.  c=getchar();
  2. buffer[0]=c;
  3. while (c == ' ' || c == '\t' || c=='\n')buffer[0]=c=getchar();  // SI ENCONTRAS UN ESPACIO, UN SALTO DE LINEA O UN TABULADOR ENTONCES SEGUI LEYENDO
  4.  

¿Está bien ese razonamiento?

Que es lo mismo que

Código
  1. while ((buffer[0] = c = getchar()) == ' ' || c == '\t' || c=='\n');

¿O me equivoco?
« Última modificación: 25 Noviembre 2015, 06:14 am por nisteeklod » En línea

LET'S DO STUFF!!
class_OpenGL


Desconectado Desconectado

Mensajes: 437

Si usas Direct3D, no eres mi amigo :P


Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #7 en: 25 Noviembre 2015, 06:15 am »

Si, está bien :D
En línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #8 en: 25 Noviembre 2015, 06:59 am »

Este es todo el programa

Código
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4.  
  5. #define MAXTOKEN 100
  6. #define NUMBER '0'
  7.  
  8. struct node {
  9.  int v;
  10.  struct node *next;
  11. };
  12.  
  13. struct node *head = NULL;
  14.  
  15. void push(int i) {
  16.  struct node *nuevo;
  17.  nuevo = (struct node *) malloc (sizeof(struct node));
  18.  if (nuevo==NULL){printf("No hay memoria suficiente.\n"); exit(-1);}
  19.  nuevo->v =i;
  20.  nuevo->next = head;
  21.  head = nuevo;
  22. }
  23.  
  24. int pop() {
  25.  
  26.  struct node *nuevo;
  27.  int aux;
  28.  
  29.  nuevo = head;
  30.  
  31.  if (!nuevo) return 0;
  32.  head = nuevo->next;
  33.  
  34.  aux = nuevo->v;
  35.  free(nuevo);
  36.  return aux;
  37.  
  38. }
  39.  
  40. int get_token(char buffer[]) {
  41.  int a,c;
  42.  
  43.  c=getchar();
  44.  buffer[0]=c;
  45.  while (c == ' ' || c == '\t' || c=='\n')buffer[0]=c=getchar();  // SI ENCONTRAS UN ESPACIO UN SALTO DE LINEA O UN TABULADOR SEGUI LEYENDO
  46.  
  47.  buffer[1] = '\0';
  48.  
  49.  if (!isdigit(buffer[0]))
  50.    return c;
  51.  
  52.  a = 0;
  53.  if (isdigit(c))
  54.    while (isdigit(buffer[++a] = c = getchar()));
  55.  
  56.  buffer[a] = '\0';
  57.  if (c != EOF)
  58.    return NUMBER;
  59. }
  60.  
  61. void mostrar_lista(){
  62.  struct node *auxiliar;
  63.  int i;
  64.  i=0;
  65.  auxiliar=head;
  66.  while (auxiliar!=NULL){
  67.      printf("%d\n", auxiliar->v);
  68.      auxiliar=auxiliar->next;
  69.      i++;
  70.  }
  71. }
  72.  
  73. int main(void) {
  74.  int type;
  75.  int n;
  76.  int sustraendo;
  77.  int divisor;
  78.  
  79.  char buffer[MAXTOKEN];
  80.  
  81.  while((type = get_token(buffer)) != EOF) {
  82.    switch(type) {
  83.    case NUMBER:
  84.      n = atoi(buffer); // convierte de cadena a entero
  85.      push(n);
  86.      break;
  87.    case '+':
  88.      push(pop() + pop());
  89.      break;
  90.    case '-':
  91.      sustraendo = pop();
  92.      push(pop() - sustraendo);
  93.      break;
  94.    case '*':
  95.      push(pop() * pop());
  96.      break;
  97.    case '/':
  98.      divisor = pop();
  99.      if (divisor != 0){
  100.          push(pop() / divisor);
  101.      }
  102.      else {
  103.          printf("¡ERROR! ¡No se puede dividir por cero!\n");
  104.      }
  105.      break;
  106.    default:
  107.      printf("error: comando desconocido %s\n", buffer);
  108.      break;
  109.    }
  110.  }
  111.  
  112.  mostrar_lista();
  113.  
  114.  return 0;
  115.  
  116. }


Calculadora polaca inversa
En línea

LET'S DO STUFF!!
class_OpenGL


Desconectado Desconectado

Mensajes: 437

Si usas Direct3D, no eres mi amigo :P


Ver Perfil
Re: [C] ¿Qué hace este while de una sola linea?
« Respuesta #9 en: 25 Noviembre 2015, 07:37 am »

Curioso. Nunca había oído hablar de la notación polaca inversa. Cada día se aprende algo :D

Una cosilla. No he analizado tu código, pero ¿no sería mejor usar
Código
  1. scanf("%d %d %c", &operando1, &operando2, &operador);
?

Ya te digo que no he analizado tu código
« Última modificación: 25 Noviembre 2015, 07:52 am por class_OpenGL » En línea

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
guardar texto en una sola linea
Programación Visual Basic
andrer03 1 1,238 Último mensaje 3 Noviembre 2008, 00:29 am
por el_c0c0
ejecutar parametro por ssh en una sola linea..
GNU/Linux
Kase 1 1,430 Último mensaje 16 Agosto 2012, 09:40 am
por adastra
CORRER UN .BAT COMPLETO EN UNA SOLA LINEA
Scripting
GEORGEFRT 2 1,681 Último mensaje 31 Agosto 2012, 23:55 pm
por GEORGEFRT
Guardar muchos datos en una sola linea de un txt para su lectura
.NET (C#, VB.NET, ASP)
cael1011 2 1,311 Último mensaje 1 Octubre 2016, 00:51 am
por cael1011
extraer texto de una cadena (1 sola línea)
Scripting
nniki999 0 2,240 Último mensaje 26 Octubre 2016, 13:02 pm
por nniki999
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines