End loop if array is empty - c

To solve my problem I need to get out of the while loop if the str2 is empty.
while (elementos <= tamanho - jogada || str2 == NULL);
This is the code:
#include <stdio.h>
#include <string.h>
#define BUFFER 100
unsigned int randaux() {
static long seed = 1;
return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff);
}
/* Implementação do procedimento MostraLamberta */
unsigned int MostraLamberta(int *tabuleiro, int tamanho) {
int i, casa, elementos;
int jogada = 0;
char novostr[BUFFER], str2[BUFFER]; /* novo vetor para receber os char */
do {
scanf("%d %d", &casa, &elementos);
for (i = 0; i < tamanho; i++) { /*Loop para percorrer o int tabuleiro um a um */
if (tabuleiro[i] == 0) { /*Comparar se for 0 vai para o vetor como O */
novostr[i] = 'O';
} else { /* Se não vai para o vetor como X */
novostr[i] = 'X';
}
}
if (tamanho >= 10) {
novostr[i] = '\0';
for (i = 1; i < tamanho; i++) {
if (i == 10) {
printf("%d", (i) / 10);
} else {
printf(" ");
}
}
printf("\n");
for (i = 1; i < tamanho + 1; i++) {
if (i >= 10) {
printf("%d", i % 10);
} else {
printf("%d", i);
}
printf;
}
} else {
for (i = 0; i < tamanho; i++) {
if (i == 10) {
printf("%d", i % 10);
} else {
printf("%d", i + 1);
}
}
}
printf("\n");
novostr[i] = '\0'; /*Termina a string */
jogada++;
printf("%s", novostr);
printf("\nJogada [%d]: %d %d", jogada, casa, elementos); /*Imprime nova string */
for (i = casa - 1; i < elementos + casa - 1; i++) {
if (tabuleiro[i] == 0) { /*Comparar se for 0 vai para o vetor como O */
novostr[i] = 'X';
tabuleiro[i] = 1;
continue;
} else { /* Se não vai para o vetor como X */
novostr[i] = 'O';
tabuleiro[i] = 0;
str2[i] = tabuleiro[i];
}
novostr[i] = '\0';
printf("%d", str2[i]);//in here if its empty, the loop is over
}
printf("\n");
} while (elementos <= tamanho - jogada || str2 == NULL);
if (jogada % 2 == 0) {
printf("Jogada inválida, perde jogador 2.");
} else {
printf("Jogada inválida, perde jogador 1.");
}
}
void main() {
int i, num, saltos, tamanho, tabuleiro[BUFFER]; /*Implementa as variáveis inteiras */
scanf("%d %d", &tamanho, &saltos);
// saltar os primeiros números aleatórios, para ter sequências distintas
for (i = 0; i < saltos; i++) /*Loop */
randaux(); /*Chama a funcão randaux */
/* Chamar o procedimento para gerar um novo tabuleiro */
for (i = 0; i < tamanho; i++) {
num = randaux(); /*Grava um numero aleatório numa nova variável */
if (num % 2 == 0) { /*VC* se o numero aleatório C) par ou impar */
tabuleiro[i] = 0;
} else {
tabuleiro[i] = 1;
}
}
MostraLamberta(tabuleiro, tamanho); /*Chama a função e passa dois argumentos) */
}
[]
[]

It is unclear what your code does, but there are some problems:
the do / while loop is an error prone construction. It is less confusing to use a for (;;) (aka for ever) loop and make explicit tests to break from it, such as if (scanf("%d %d", &casa, &elementos) != 2) break;
the second part of the test while (elementos <= tamanho - jogada || str2 == NULL); is moot: str2 is an array, it cannot be NULL. If you want to test for an empty string, use str2[0] == '\0' instead.
str2 is not properly constructed: the only place where it gets modified is: str2[i] = tabuleiro[i]; but tabuleiro[i] is set to 0 just before this statement, so part of str2 is uninitialized and the only elements that get modified are null bytes.

In the OP code, the following lines get into infinite loop.
while (elementos <= tamanho - jogada || str2 == NULL);
Few potential issues to look at:
The 'str2' expression is always NON-null. Recall that in "C", the value of an array is the address of the first element. If you want to test is a string is "empty" consider strlen(str2) == 0, or similar.
For any case that str2 is "not empty", the while will go into infinite loop if elementos <= tamanho - jogada. Usually, you will see modification to one of the variables in the condition inside the loop body. e.g. jopada++

Related

I am trying to make a scanf that checks if the user has input only numbers or char mixed with numbers

I have to make a program that reads an integer (N+) and then read a series of other integers (N+), but the program needs to check if the user has inputted chars mixed in the numbers the scanf() reads, in affirmative, the program will repeat the scanf(). So I decided to check the return value of scanf(). It works if I use only character input, but when I mixed it with integers, the program reads the integer and uses the maintained character on the buffer. How can I solve this?
#include <stdio.h>
int main() {
int tamanho = 0, verificador = 0;
do {
printf("Digite um valor n>0: ");
verificador = scanf("%d", &tamanho);
getchar();
if (verificador != 1) {
printf("\nO programa aceita apenas valores inteiros\n");
printf("Tente novamente\n");
}
} while (verificador != 1);
int conjunto[tamanho];
do {
printf("Digite os numeros do conjunto de tamanho 'n': ");
for (int i = 0; i < tamanho; i++) {
verificador = scanf("%d", &conjunto[i]);
if (verificador != 1) {
printf("\nO programa aceita apenas números\n");
printf("Tente novamente\n");
getchar();
break;
}
}
} while (verificador != 1);
printf("numero = %d\n", tamanho);
for (int i = 0; i < tamanho; i++) {
if (i <= tamanho - 2) {
printf("%d, ", conjunto[i]);
} else if (i == tamanho - 1) {
printf("%d.\n", conjunto[i]);
}
}
return 0;
}

Problem on adding element with a loop for in an array in c

My goal is to separate each word from a string and store the separated words in an array.
Everything seems to be going well but the final table is only filled with the last word and I can't understand why.
Please find my code below:
enum {TAILLE_BUFFER = 100};
char la_commande[TAILLE_BUFFER];
char* tableauArguments[TAILLE_BUFFER];
char* espace = " ";
printf("Rentrez la commande à executer avec ses arguments\n");
scanf("%[^\n]s", la_commande);
printf("%s\n", la_commande);
int cpt = 0;
int dernier_espace = 0;
int lenTab = 0;
for(int i = 0; i < TAILLE_BUFFER; i++)
{
if( (int)la_commande[i] == 0 ){
break;
}
lenTab++;
}
for(int cpt1 = 0; cpt1 < lenTab + 2; cpt1++)
{
int taille = cpt1 - dernier_espace;
char le_mot[taille];
if(la_commande[cpt1] == 32 )
{
for(int i = 0; i < taille; i++)
{
le_mot[i] = la_commande[i + dernier_espace];
}
printf("test1 : %s %d\n", le_mot, cpt);
tableauArguments[cpt] = le_mot;
printf("test2 %s\n", tableauArguments[cpt]);
dernier_espace = cpt1;
cpt++;
}
}
for(int cp1 = 0; cp1 < 5; cp1++)
{
printf("\nLecture du tableau : %s numero : %d", tableauArguments[cp1], cp1);
}
you couldn't do that: tableauArguments[cpt] = le_mot; because you didn't allocate memory location for tableauArguments[TAILLE_BUFFER] double array. Even if you allocate, you have to use 'strcpy()' fucntion to copy content of a string array to another one.
The working code may be like that:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char la_commande[100];
char tableauArguments[100][100];
char* espace = " ";
printf("Rentrez la commande à executer avec ses arguments\n");
scanf("%[^\n]s",la_commande);
printf("%s\n",la_commande);
int cpt = 0;
int dernier_espace = 0;
int lenTab= 0;
for(int i = 0; i < 100; i++)
{
if((int)la_commande[i] == 0){
break;
}
lenTab++;
}
for(int cpt1 = 0; cpt1 < lenTab+2; cpt1++) {
int taille = cpt1 - dernier_espace;
char le_mot[taille];
if(la_commande[cpt1] == 32 )
{
for(int i = 0; i < taille;i++){
le_mot[i] = la_commande[i+dernier_espace];
}
printf("test1 : %s %d\n",le_mot,cpt);
strcpy(tableauArguments[cpt], le_mot);
printf("test2 %s\n",tableauArguments[cpt]);
dernier_espace = cpt1;
cpt++;
}
}
for(int cp1 = 0; cp1 < 5;cp1++){
printf("\nLecture du tableau : %s numero : %d", tableauArguments[cp1], cp1);
}
}

Break of FOR loop after switch - C

int realizar_reparaciones(int naves_a_reparar, int repuestos_laser, int repuestos_escudos, int repuestos_compensadores){
int caracter_valido = 0;
char reparacion_necesaria;
int naves_con_alambre = 0;
int contador_laser = 0;
int contador_escudo = 0;
printf ("A continuación deberá ingresar uno de los siguientes valores por nave: L (Generador Láser) o E (Generador de escudo deflector)\n");
for (int i = 1; i <= naves_a_reparar; i = i + 1){
while (caracter_valido == 0){
printf ("Ingrese la reparación que hay que realizarle a la nave %d: ", i);
scanf (" %c", &reparacion_necesaria);
switch (reparacion_necesaria){
case 'L':
if (repuestos_laser == 0){
naves_con_alambre = naves_con_alambre + 1;
} else {
repuestos_laser = repuestos_laser - 1;
contador_laser = contador_laser + 1;
}
caracter_valido = 1;
break;
case 'E':
if (repuestos_escudos == 0){
naves_con_alambre = naves_con_alambre + 1;
} else {
repuestos_escudos = repuestos_escudos - 1;
contador_escudo = contador_escudo + 1;
}
caracter_valido = 1;
break;
default:
printf ("Ingrese unicamente alguno de los caracteres previamente mencionados\n");
break;
}
}
}
printf ("Se utilizaron %d generadores láser\n", contador_laser);
printf ("Se utilizaron %d generadores de escudos deflectores\n", contador_escudo);
printf ("Se utilizaron %d compensadores de aceleracion\n", contador_compensador);
return naves_con_alambre;
I have this function in C. i can only get the FOR to run once even if "naves_a_reparar" is 30 or any high number. After that, it goes out of the FOR loop and function ends. Why is this happening?

I have problems to compile a method with a multidimensional array

I need to display a board who have this structure
only with O - | chars
Have this error
main.c:17:29: error: expected primary-expression before ‘]’ token
desplegar_tablero(&tablero[][],fil,col);
(still not complete the algorithm but i'm working in it)
int main(int argc, char **argv){
if (argc != 3){
fprintf(stderr, "Ejecutar como ./prog N_filas N_columnas.\n");
exit(EXIT_FAILURE);
}
int fil = 2*(atoi(argv[1]))-1;
int col = 2*(atoi(argv[2]))-1;
char tablero[fil][col];
desplegar_tablero(&tablero[][],fil,col);
}
void desplegar_tablero(char tab[][], int f, int c){
for (int i = 1; i<= f; ++f){
for (int j = 1; j <=c; ++c){
//Si fila es impar
if (i%2 == 1){
//Columna Impar
if (j%2 == 1){
// ASCII 79 = O
tab[i][j]= 79;
printf(" %u ",&tab[i][j]);
}
//Columna par
else{
// ASCII 196 = -
tab[i][j] = 196;
printf(" %u ",&tab[i][j]);
}
}
// Si fila par
else{
//Columna impar
if (j%2==1){
// ASCII 179 = |
tab[i][j]= 179;
printf(" %u ",&tab[i][j]);
}
//Columna par
else{
// ASCII 32 = espacio
tab[i][j] = 32;
printf(" %u ",&tab[i][j]);
}
}
printf("\n");
}
}
}

C - Function is not counting the correct amount of given character

as said on the title, my function is not calculating the correct amount os characters in a given string.
The function is this one:
void contar(char **texto, int *quantidade, int N)
{
int i, j, aux;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
aux = (int) texto[i][j];
/* If upper case */
if(64 < aux && aux < 91)
{
aux = aux - 65;
quantidade[aux]++;
}
/* If lower case */
else if(96 < aux && aux < 123)
{
aux = aux - 71;
quantidade[aux]++;
}
}
}
for(i=0;i<52;i++)
{
printf("\n i-%d %d\n", i, quantidade[i]);
}
}
My objective is: take the character, check his number according to the ASCII table. If the number represents an Upper Case Character, I subtract it by 65 and use it as the index of my vector and increment the vector in that position. If it is a Lower Case Character, I subtract it by 71, because the last Upper Case Character is Z, which corresponds to 90. And the 'a' corresponds 97. So 90 - 65 = 25 and 97 - 65 = 32, as I dont wanna leave this gap in the vector, I do 97 - 65 - 6.
What is happening is that, for certain characters, the function is counting 1 character less.
For example, on the text below, the function counts only 5 'A', when there is actually 6.
Duvidas Frequentes E um grau do ensino superior obtido em cursos de
Graduacao, ministrados pela Universidade, destinados a alunos que
tenham concluido o ensino medio ou equivalente. A Unicamp oferece
cursos de Graduacao em diferentes areas do conhecimento. A estrutura
de ensino e pesquisa da Unicamp esta, em sua maior parte, no campus de
Barao Geraldo, em Campinas. Em Piracicaba funciona a Faculdade de
Odontologia de Piracicaba (FOP); em Limeira, a Faculdade de Tecnologia
(FT) e Faculdade de Ciencias Aplicadas (FCA); em Paulinia, o Centro de
Pesquisas Quimicas, Biologicas e Agricolas (CPQBA); em Sumare, o
Hospital Estadual; e, em Hortolandia, o Hospital Mario Covas.
The rest of the code is the following one:
#include <stdio.h>
#include <stdlib.h>
void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N);
void matriz_ascii(char **texto, int **ascii, int N);
void ordenar(int *quantidade, int *prioridade);
void contar(char **texto, int *quantidade, int N);
int checarMaior(int *quantidade, int i);
void troca(int **ascii, int *prioridade, int N);
int main()
{
int N, i, j, quantidade[52], prioridade[26], **ascii;
char **texto;
for(i=0;i<52;i++)
{
quantidade[i] = 0;
}
for(i=0;i<26;i++)
{
prioridade[i] = 0;
}
scanf("%d", &N);
setbuf(stdin, 0);
texto = malloc(N * sizeof(char *));
ascii = malloc(N * sizeof(char *));
for(i=0;i<N;i++)
{
texto[i] = malloc(501 * sizeof(char));
ascii[i] = malloc(501 * sizeof(char));
}
for(i=0;i<N;i++)
{
fgets(texto[i], 501, stdin);
}
encriptar(texto, ascii, quantidade, prioridade, N);
for(i=0;i<N;i++)
{
for(j=0;texto[i][j];j++)
{
texto[i][j] = (char) ascii[i][j];
}
}
printf("\n");
for(i=0;i<N;i++)
{
printf("%s", texto[i]);
}
printf("\n");
for(i=0;i<26;i++)
{
printf("%d ", prioridade[i]);
}
printf("\n");
return 0;
}
void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N)
{
matriz_ascii(texto, ascii, N);
contar(texto, quantidade, N);
ordenar(quantidade, prioridade);
troca(ascii, prioridade, N);
}
void matriz_ascii(char **texto, int **ascii, int N)
{
int i, j;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
ascii[i][j] = (int) texto[i][j];
}
}
}
void contar(char **texto, int *quantidade, int N)
{
int i, j, aux;
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!=0;j++)
{
/*aux = (int) texto[i][j];
printf("%d ", aux); */
/* Se for maiusculo */
if(65 <= texto[i][j] && texto[i][j] <= 90)
{
aux = texto[i][j] - 65;
quantidade[aux]++;
}
/* Se for minusculo */
else if(97 <= texto[i][j] && texto[i][j] <= 122)
{
aux = texto[i][j] - 71;
quantidade[aux]++;
}
}
printf("\n");
}
/*for(i=0;i<52;i++)
{
printf("\n i-%d %d\n", i, quantidade[i]);
}*/
}
void ordenar(int *quantidade, int *prioridade)
{
int i, i_maior;
for(i=0;i<26;i++)
{
quantidade[i] += quantidade[i+26];
}
for(i=0;i<26;i++)
{
i_maior = checarMaior(quantidade, 0);
quantidade[i_maior] = -1;
prioridade[i] = i_maior;
}
}
int checarMaior(int *quantidade, int i)
{
int i_maior = i, maior = quantidade[i];
for(i=i+1;i<26;i++)
{
if(quantidade[i] > maior)
{
maior = quantidade[i];
i_maior = i;
}
else if(quantidade[i] == maior)
{
if(i < i_maior)
{
i_maior = i;
}
}
}
return i_maior;
}
void troca(int **ascii, int *prioridade, int N)
{
int i, j, i_aux, i_num, aux, valor = -1;
for(i=0;i<N;i++)
{
for(j=0;ascii[i][j];j++)
{
aux = ascii[i][j];
/* Se for maiusculo */
if(64 < aux && aux < 91)
{
aux = aux - 65;
valor = 1;
}
/* Se for minusculo */
else if(96 < aux && aux < 123)
{
aux = aux - 97;
valor = 0;
}
else
{
valor = -1;
}
if(valor != -1)
{
for(i_aux=0;i_aux<26;i_aux++)
{
if(prioridade[i_aux] == aux)
{
i_num = i_aux;
}
}
if(i_num % 2 == 0)
aux = prioridade[i_num+1];
else
aux = prioridade[i_num-1];
if(valor == 1)
ascii[i][j] = aux + 65;
else if(valor == 0)
ascii[i][j] = aux +97;
}
}
}
}
Any ideas of what I am doing wrong?
Thanks in advance!
The quantidade function seems OK. But this loop in matriz_ascii has a problem:
for(i=0;i<N;i++)
{
for(j=0;texto[i][j]!='\0';j++)
{
ascii[i][j] = (int) texto[i][j];
}
}
This does not copy the null-terminator. But later on, in troca you have a loop that runs until ascii[i][j] == 0;. That loops will run off the end of the copied values until they happen to come across a 0 in other memory, which is bad.
As you point out in comments, you malloc the wrong amount of space also (on two different lines). You could have avoided that by using this idiom:
texto = malloc(N * sizeof *texto);
ascii = malloc(N * sizeof *ascii);
for(i=0;i<N;i++)
{
texto[i] = calloc(501, sizeof *texto[i]);
ascii[i] = calloc(501, sizeof *ascii[i]);
}
The reason I use calloc is so that if your fgets lines fail (e.g. due to end of input) then your array contains blank strings, which your code handles correctly. Without that, a short input file would cause your code to operate on uninitialized memory.
Other things you can do to make your code more readable and robust:
replace magic numbers like 65 with 'A',
replace loops that set things to 0 with initialization to = { 0 };, or calloc
Check that malloc does not return NULL.
Also you should make more of an effort to debug before posting on here. If something is not working, then change your code to add extra debugging output (or use a debugger) until you find out exactly which little piece is causing the program to go from good to bad. Also you can try valgrind.

Resources