Curso completo de programación con lenguaje C

bornex

#540 xD lo he arreglado y lo tengo ya más elegante, me han dado un par de collejas ya por lo mismo.

typedef struct{
	char name[20];
	int lvl;
} Personaje;
1 respuesta
cabron

#541

Realmente tampoco pasa nada si haces un typedef directamente al puntero, pero es mejor si lo pones de forma explícita que es un puntero:

typedef struct personaje{
        char name[20];
        int lvl;
} personaje, *p_personaje;

De esta forma puedes crear un struct normal y un puntero al struct sin confundirte:

//struct
personaje p1; 
p1.lvl = 4;

//puntero a struct
p_personaje p2= malloc(sizeof(personaje));
p2->lvl = 4;

//y por supuesto también funciona
personaje *p3= malloc(sizeof(personaje)); 
p3->lvl = 4;
1 respuesta
herre

#542 Mi forma de verlo es que es un tipo adicional innecesario, mejor usar

Tipo *ptr;

Pero nos estamos llendo por las parras xD

7 días después
bornex

Buenas! vengo con otra dudilla sobre C que me esta surgiendo leyendome el K&R.

Imaginemos que tenemos un main tal que así:

#include <stdio.h>

#define MAXLINE  100

main(){
    double sum, atof(char []);  // aquí
    char line[MAXLINE];
    int getline(char line[], int max);   // y aquí

sum = 0;
while(getline(line, MAXLINE) > 0){
     printf("\t%g\n", sum += atof(line));
}
return 0;
}

¿Qué es lo que hace exactamente en las lineas que he señalado?

Según el libro, la primera declaración dice que atof es una función que le entra como parámetro un array de char y que devuelve un tipo double, pero ¿para qué?.

Además, dice que la función atof() debe estar definida consistentemente, supongo que con esto se refiere a que en algún lugar del mismo fichero fuente este esa función declarada con la misma cabecera que ahí se pone. ¿No es mejor hacer los prototipos de las funciones fuera del main?

La verdad es que lo usa en varios sitios, y parecen como prototipos de funciones dentro de funciones.

A ver si alguien me aclara algo más sobre el tema. :)

2 respuestas
gonya707

#544 atof efectivamente es una funcion que a partir de un caracter te saca un float, vamos, es alpha to float, de ahi su nombre, pero no entiendo ese uso en la linea 6, entiendo que ahi esta creando una variable.

la linea 8 es solo el prototipo de una funcion, no tiene mas, la funcion getline, parametros de entrada una string llamada line y un entero llamado max, devuelve un entero a su salida

1 respuesta
bornex

#545 la linea 6 y la 8 hacen lo mismo (creo yo), es decir, hacen 2 prototipos de función. Entonces, eso significa lo mismo ¿qué si pongo los prototipos de función fuera del main?.

Es que, en el quicksort que hace también en el libro, usa exactamente lo mismo, hace un prototipo de la función swap dentro de la propia función qsort().

EXPLICACIÓN SOBRE PROTOTIPOS DE FUNCIÓN

En C, el valor que devuelve una función puede ser omitido, es decir, puedes declarar una función tal que así:

main(){
    // código
}

Si el valor que devuelve una función es omitido, se asume que el valor que devuelve esa función es de tipo int.

Cuando el valor de una función no es de tipo int, es decir, void, double, float, ... tenemos que decirle al compilador que esa función NO DEVUELVE UN TIPO INT para ello, se debe de declarar un prototipo de la función antes de su primer uso, en cualquier parte del código.

Si tenemos:

main(){
    printf("%f\n", funcion1(3.0, 2.0));
    return 0;
}

double funcion1(double x, double y){
    return x+y;
}

Nos dará un error en tiempo de compilación, pero si declaramos el prototipo de la función para que el compilador sepa que tipo devuelve, todo irá bien:


double funcion1(double x, double y);

main(){
    printf("%f\n", funcion1(3.0, 2.0));
    return 0;
}

double funcion1(double x, double y){
    return x+y;
}

Como hemos dicho, el prototipo se debe especificar antes de su primer uso, entonces, esto es igualmente válido:

main(){
    double funcion1(double x, double y);
    printf("%f\n", funcion1(3.0, 2.0));
    return 0;
}

double funcion1(double x, double y){
    return x+y;
}

Por contra, esto también es válido por lo anteriormente comentado:

main(){
    printf("%d\n", funcion1(3, 2));
    return 0;
}

int funcion1(int x, int y){
    return x+y;
}

Aquí ya no es necesario el prototipo de función, porque cuando el compilador llegue a leer la línea 2, sabrá que, como nadie le ha especificado lo contrario, el valor que devuelve funcion1() es un int.

herre

#544

El K&R es un libro importante históricamente pero la verdad es que está muy anticuado. Nadie debería usarlo para aprender C.

En la linea 6 está declarando una variable y el prototipo de una función.
En la línea 8 está declarando el prototipo de otra función.

Ambos prototipos son sólo visibles dentro de main().

Nunca escribas C así hoy en día.

2 respuestas
bornex

#547 Ok, lo apunto, joder es que estoy siguiendolo y ya me has quitado to' las ganas de seguirlo xD.

¿Otro libro que me recomiendas?

1 respuesta
herre

#548 http://c.learncodethehardway.org/book/

EDIT: Obviamente, #1 es otra gran opción xD

1 2 respuestas
bornex

#549 Vale ese libro me lo recomendaste por MP, voy a leermelo :) gracias tio!

#547 Vengo a preguntar otra dudilla que tengo.

¿Cómo debo de declarar un struct que representa el nodo de una lista?

typedef struct {
        int dato;
        Nodo *next;
} Nodo;

Este código me da error, diciendome que Nodo *next no sabe lo que es.

La siguiente forma es la que viene en K&R que supongo que está mal (en Learn C The Hard Way tampoco viene):

typedef struct node *NodoPtr;

typedef struct node{
        int dato;
        NodoPtr next;
} Nodo;

¿Es correcta?

1 respuesta
herre

#550 Lo más facil es

typedef struct Node {
    int dato;
    struct Node *next;
} Node;

PD: los "typedef" y los structs tienen namespaces separados, puedes llamarlos igual, veo a mucha gente q llama a los structs foo_s y a los tipos foo innecesariamente.

1
xonde

#549
Mucha gente considera que el libro "learn C, the hard way" es un mal recurso para aprender C. Algunos enlaces y referencias a un buen material para aprender C los puedes encontrar en este enlace:
http://www.iso-9899.info/wiki/Main_Page#Stuff_that_should_be_avoided

1 respuesta
herre

#552 No estoy de acuerdo, es un buen recurso. No es perfecto, pero es bueno.

No debe ser el único recurso que se use, pero sigo recomendándolo.

PD: Zed A Shaw es un tio peculiar que o te cae bien o le odias, y mucha gente de este seguno grupo aprovecha para darle palos como pueden. La realidad es que es un programador de puta madre y un buen profesor, y tiene buen método. El libro es una "beta" así que no engaña a nadie.

20 días después
B

despues de dejar el curso en el capitulo de punteros/arrays, vuelvo a la carga.

lo conseguire completar? nosesabe.

B

#173 bueno, estoy con esta leccion liado.

dejo todo el codigo para que le eches un vistazo y me digas que tal va:

spoiler

El problema esta en la funcion comprobarHuecosArray(). en el ejercicio apuntas :
-añadir un número distinto de 0 al array
-comprobar cuantos huecos libres quedan en el array

y voy a poner ambos en una misma funcion, es decir, que compruebe los valores del array y si son igual a 0, que le diga al usuario si quiere o no modificarlos. hasta ahi bien, no?

comprueba el codigo (seguro que se puede mejorar, pero estoy haciendo pruebas y ya se sabe como es el codigo de pruebas XD) y me dices si va bien o no. el caso es que cuando lo ejecuto (compilo con gcc 4.9.3), no se para en la linea 52, esperando la entrada del usuario.

puede ser porque la funcion es void? estoy perdido en este aspecto.

1 respuesta
joked9

Para crear un programita que genere x numeros de 8 cifras aleatorios sin que se repitan... Le estoy dando vueltas pero nada vaya.

2 respuestas
B

#556 coge boli y papel y ve planteando lo que quieres. mi planteamiento es una mierda, :psyduck:

inicia el programa
quiero 8 numeros, donde los guardo? en un array?
no quiero que se repitan, como se hace? comprobando...

ya diras que tal.

LeeSinGafas

#556

1 - Crea una array donde se almacenen todos los números
2 - Genera el número
3 - Recorre el array para comprobar si el número se repite (con el típico bucle for)
4 - En caso de no estar se almacena, en caso de estar no se almacena
5 - Repetir paso 2 - 4 hasta tener los números deseados

Yo lo plantearía así, no es que sea un experto en programación, pero no parece muy complicado

2
joked9

Gracias chicos!!! ^^

B

#555

Creo que lo de la linea 52, así a ojo y sin compilar para probar, puede que sea por no referenciar a modificacion correctamente, tal que: &modificacion

void no tiene que ver ya que el tipo de dato que acompañan a las funciones es el de lo que retorna esta y en este caso, no regresas nada, por tanto void, sería correcto.

Un saludo!

P.S: El ejercicio acabo de leerlo y no me gusta mucho, con arrays normalmente se trabaja dejando los huecos al final y añadir insertando en x posición y eliminar x posicion sobrescribiendo parte de array, pero bueno, el resto de aclaraciones que te las haga quien lleva el hilo.

Edito:
He visto que tienes lio con el tipo de variables de retorno, por ejemplo main se suele definir como int porque al final se devuelve por lo general un 0, return 0; para saber si el código se ha ejecutado correctamente.

Otro ejemplo es en borrarArray, la defines como int pero en realidad no estás devolviendo nada, solo borras, por tanto debería ser void. Cuando se le pone tipo de variable de retorno distinto de void a una función? Ejemplo super rapido:

int sumar(int x, int y){
    int resultado;

resultado = x + y;

return resultado;
}

Algo simple, suma de enteros y nos devuelve el resultado. En el main podremos imprimir el resultado facilmente tipo la suma de x e y es suma(x,y).

1 1 respuesta
B

#560 perfecto. corregido todo, cuando acabe codigo publico y lo revisais.

1
1 mes después
Camp1

hola buenas venia a preguntar algo..

El caso es que tengo una estructura con matrices y tal y tengo que hacer una nueva estructura con los datos de la misma ( hacer una copia vamos ) . Existe algún método para hacerlo directamente o tengo que hacer un bucle para ir copiando todos los elementos de las matrices ?

2 respuestas
B

#562

Estoy bastante oxidado programando en C, pero con memcpy debería bastar

void copiarMatriz (void * matrizDestino, void * matrizOrigen) 
{
  memcpy(matrizDestino , matrizOrigen, ROWCOUNT*COLUMNCOUNT*sizeof(int));
}
herre

#562 Si el struct guarda la matriz como un array:

struct Foo {
    float matrix[9];
};

puedes hacer simplemente:

Foo a;
// ...
Foo b = a;

Si guardas un puntero a la matriz, puedes usar memcpy.

1
13 días después
B

Hola!
Tengo una pequeña duda.

Para pasar parámetros a una función que te retorna un valor (da igual el tipo) se suelen utilizar punteros a funció. Mi duda es:

int variable
variable=(int)FUNCION

Es correcto, el retorno de la función te lo guarda en variable.

¿Podrías pasar parámetros utilizando la misma gramática?

int variable, var1;
char var2;
variable=(int)FUNCION(int var1, char var2)

No sé utlitzar lo de insertar el código xDD

2 respuestas
gonya707

#565 no entiendo nada de tu pregunta. Se dice sintaxis, no gramatica por cierto xD

intuyo que lo que querias poner en tu primer codigo era esto, si no no me entero con esa sintaxis

int variable = funcion();
marod

#565

Creo que más o menos te he entendido, pero para la próxima intenta poner nuevas lineas entre código.

Tu puedes guardar lo que retorne una función en una variable siempre que sea del mismo tipo de lo que estás devolviendo.

Imagínate que tienes un función que hace una suma y una variable global que guardara esa suma:


int sumaTotal = 0;

int FuncionSuma(int num1 , int num2)
{
int suma = num1 + num2;
return suma;
}

sumaTotal = FuncionSuma( 5, 5) ;
// FuncionSuma devolvera 10, y se guardara en la variable sumaTotal, pasando a ser sumaTotal = 10 porque sumaTotal es un int y FuncionSuma devuelve int. Si no, daría error.

Por tanto, tú a función suma le puedes pasar un char, un float o un booleano, pero lo que devuelva debe ser del mismo tipo de lo que hayas instanciado la función. Y si lo que quieres es guardar en otra variable lo que devuelva la función, debe ser del mismo tipo que lo que devuelva.

Te pongo otro ejemplo, con tu ejemplo:

int variable, var1 = 15;
char var2;

int Función(int variable1, char variable2)
{
print(variable2);
return variable1;
}

variable = Función(var1,var2);
//Por consola saldrá lo que había en variable2 y además se instancia la variable "variable" con lo que ha devuelto la función que es int (Como la función), qué seria 15. variable = 15;

Creo que era eso lo que preguntabas...

14 días después
KooPad

Cuál es la mejor forma de plantear un problema recursivo?
Ya no pasarlo a código, sino como pensarlo. Ejemplo:

Si tengo esta lista, quiero imprimir los n/2 elementos de esta al revés:

a b c d, quiero imprimir d c

1 respuesta
B

#568

Lo normal es primero plantearte uno o varios casos base, los más básicos que es cuando el programa deberá acabarse y luego pensar en como invocar a la propia función para llegar a este.

Ejemplo clásico de la recursividad:

int factorial(int n){
    /*planteamos un caso base,que sería para n == 0 o n==1, devolver 1, a gusto de cada uno*/
    if (n==0){
        return 1;
    }
    else{
        /*devolvemos el resultado de multiplar n por su anterior hasta que n valga 0 que devolverá 1 y no se llamará más a si misma*/
        return n*factorial(n-1);
    }
}

La recursividad principalmente me la he encontrado a la hora de trabajar con árboles donde se ven otros usos y su utilidad, si te interesa el tema y sabes algo de algoritmia tira por esa vía para aprender algo más.

Un salduo.

1 1 respuesta
KooPad

#569 Los problemas recursivos numéricos no son del todo difíciles, la cosa se me complica al entrar en problemas tipo Hanoi y similares

1 respuesta