Desafio: Soma de argumentos #19

Open
opened 2025-06-04 16:05:46 -03:00 by NRZCode · 1 comment

Encontrei 3 a 4 formas de converter uma string|caracter em inteiro afim de ser possível somá-los.

Subtração de '0'

Subtraindo 0 (char), que na tabela ASCII tem o valor decimal 48, é possível converter o caracter para inteiro.
Usando um loop aritmético é possível converter uma string numérica em inteiro.

char c = argv[1][0];
int num = c - '0';
printf("O valor inteiro do primeiro caracter de argv[1]: \"%c\" é %d\n", c, num);

printf("Conversão da string \"%s\" em inteiro é %d (subtração de '0')\n", argv[1], strtoint(argv[1]));
int strtoint(char *str) {
    int num = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        if (str[i] >= 48 && str[i] <= 57) {
            num = num * 10 + (str[i] - '0');
            // printf("O valor inteiro do character [%c] é %d\n", str[i], num);
        } else
            break;
    }
    return num;
}

Usando a função sscanf

sscanf, vsscanf - input string format conversion

int num;
char c = argv[1][0];
sscanf(&c, "%d", &num);
printf("O valor inteiro do primeiro caracter de argv[1] \"%c\" é %d\n", c, num);

char *str = argv[2];
sscanf(str, "%d", &num);
printf("Conversão da string \"%s\" em inteiro é %d\n", str, num);

Usando a função atoi

A função atoi de stdlib.h
atoi, atol, atoll - convert a string to an integer

char c = argv[1][0];
int num = atoi(&c);
printf("O valor inteiro do primeiro caracter de argv[1]: \"%c\" é %d\n", c, num);

char *str = argv[3];
num = atoi(str);
printf("Conversão da string \"%s\" em inteiro é %d (atoi)\n", str, num);

Usando dprintf

Apesar de não parecer sua função primordial, dprintf conseguiu realizar a conversão para inteiro.

int dprintf(int fd,                                                                                                              
    const char *restrict format, ...);
int num;
char *str = argv[1][0];
dprintf(num, "%s", str);
printf("Conversão da string \"%s\" em inteiro é %d (dprintf)\n", str, num);
int main(int argc, char **argv) {
    if (argc < 4)
        return 1;

    int num1, num2, num3;
    // dprintf(num1, "%s", argv[1]); // Imprime no fd de num1 ao invés de stdio
    sscanf(argv[1], "%d", &num1);
    num2 = strtoint(argv[2]);
    num3 = atoi(argv[3]);
    printf("A soma de %d + %d + %d = %d\n", num1, num2, num3, num1 + num2 + num3);

    return 0;
}
Encontrei 3 a 4 formas de converter uma string|caracter em inteiro afim de ser possível somá-los. ## Subtração de '0' Subtraindo 0 (char), que na tabela ASCII tem o valor decimal 48, é possível converter o caracter para inteiro. Usando um loop aritmético é possível converter uma string numérica em inteiro. ```c char c = argv[1][0]; int num = c - '0'; printf("O valor inteiro do primeiro caracter de argv[1]: \"%c\" é %d\n", c, num); printf("Conversão da string \"%s\" em inteiro é %d (subtração de '0')\n", argv[1], strtoint(argv[1])); ``` ```c int strtoint(char *str) { int num = 0; for (int i = 0; str[i] != '\0'; i++) { if (str[i] >= 48 && str[i] <= 57) { num = num * 10 + (str[i] - '0'); // printf("O valor inteiro do character [%c] é %d\n", str[i], num); } else break; } return num; } ``` ## Usando a função sscanf sscanf, vsscanf - input string format conversion ```c int num; char c = argv[1][0]; sscanf(&c, "%d", &num); printf("O valor inteiro do primeiro caracter de argv[1] \"%c\" é %d\n", c, num); char *str = argv[2]; sscanf(str, "%d", &num); printf("Conversão da string \"%s\" em inteiro é %d\n", str, num); ``` ## Usando a função atoi A função atoi de stdlib.h atoi, atol, atoll - convert a string to an integer ```c char c = argv[1][0]; int num = atoi(&c); printf("O valor inteiro do primeiro caracter de argv[1]: \"%c\" é %d\n", c, num); char *str = argv[3]; num = atoi(str); printf("Conversão da string \"%s\" em inteiro é %d (atoi)\n", str, num); ``` ## Usando dprintf Apesar de não parecer sua função primordial, dprintf conseguiu realizar a conversão para inteiro. ```c int dprintf(int fd, const char *restrict format, ...); ``` ```c int num; char *str = argv[1][0]; dprintf(num, "%s", str); printf("Conversão da string \"%s\" em inteiro é %d (dprintf)\n", str, num); ``` ```c int main(int argc, char **argv) { if (argc < 4) return 1; int num1, num2, num3; // dprintf(num1, "%s", argv[1]); // Imprime no fd de num1 ao invés de stdio sscanf(argv[1], "%d", &num1); num2 = strtoint(argv[2]); num3 = atoi(argv[3]); printf("A soma de %d + %d + %d = %d\n", num1, num2, num3, num1 + num2 + num3); return 0; } ```
Owner

@NRZCode wrote in #19 (comment):

Subtração de '0'

Subtraindo 0 (char), que na tabela ASCII tem o valor decimal 48, é possível converter o caracter para inteiro. Usando um loop aritmético é possível converter uma string numérica em inteiro.

Olha uma versão em assembly:

; ----------------------------------------------------------
; Arquivo : uint.asm
; Montagem: nasm -g -f elf64 uint.asm
; Ligação : ls uint.o -o uint
; ----------------------------------------------------------
section .data
; ----------------------------------------------------------
	nstr db "123", 0  ; string numérica
; ----------------------------------------------------------
section .bss
; ----------------------------------------------------------
	num resq 1	  ; 8 bytes (long) para o valor
; ----------------------------------------------------------
section .text
; ----------------------------------------------------------
global _start
_start:
; ----------------------------------------------------------
; Conversão da string numérica em 'nstr' para o inteiro
; decimal correspondente...
; ----------------------------------------------------------
	xor rax, rax	  ; rax = 0 (acumula o resultado)
	mov rsi, nstr	  ; endereço do primeiro byte da string
_conv_loop:
	mov bl, [rsi]	  ; carrega o dígito corrente em rbx
	test bl, bl	  ; verifica se o byte é o terminador 0x00
	je .done	  ; se for, salta para o fim da rotina

	sub rbx, 0x30	  ; converte o dígito para seu valor numérico
	imul rax, rax, 10 ; rax *= 10 (deslocamento do peso posicional)
	add rax, rbx	  ; rax += novo algarismo
	inc rsi		  ; avança para o próximo byte
	jmp _conv_loop
.done:
	mov [num], rax	  ; armazena o valor final na memória
; ----------------------------------------------------------
_exit:
; ----------------------------------------------------------
	mov rax, 60
	mov rdi, 0
	syscall

Tem que ver o resultado no GDB, o programa não imprime.

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/19#issue-19: > ## Subtração de '0' > > Subtraindo 0 (char), que na tabela ASCII tem o valor decimal 48, é possível converter o caracter para inteiro. Usando um loop aritmético é possível converter uma string numérica em inteiro. Olha uma versão em assembly: ```asm ; ---------------------------------------------------------- ; Arquivo : uint.asm ; Montagem: nasm -g -f elf64 uint.asm ; Ligação : ls uint.o -o uint ; ---------------------------------------------------------- section .data ; ---------------------------------------------------------- nstr db "123", 0 ; string numérica ; ---------------------------------------------------------- section .bss ; ---------------------------------------------------------- num resq 1 ; 8 bytes (long) para o valor ; ---------------------------------------------------------- section .text ; ---------------------------------------------------------- global _start _start: ; ---------------------------------------------------------- ; Conversão da string numérica em 'nstr' para o inteiro ; decimal correspondente... ; ---------------------------------------------------------- xor rax, rax ; rax = 0 (acumula o resultado) mov rsi, nstr ; endereço do primeiro byte da string _conv_loop: mov bl, [rsi] ; carrega o dígito corrente em rbx test bl, bl ; verifica se o byte é o terminador 0x00 je .done ; se for, salta para o fim da rotina sub rbx, 0x30 ; converte o dígito para seu valor numérico imul rax, rax, 10 ; rax *= 10 (deslocamento do peso posicional) add rax, rbx ; rax += novo algarismo inc rsi ; avança para o próximo byte jmp _conv_loop .done: mov [num], rax ; armazena o valor final na memória ; ---------------------------------------------------------- _exit: ; ---------------------------------------------------------- mov rax, 60 mov rdi, 0 syscall ``` Tem que ver o resultado no GDB, o programa não imprime.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: blau_araujo/cblc#19
No description provided.