working with methods to take in strings in C - arrays

I'm new to C and am having a lot of issues with arrays that keeps coming up. I'm trying to write a method that takes in a string ("1234") and returns the odd digits, however it keeps printing 49 and I don't know why? Does it have something to do with how I'm assigning the arrays?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int print_odd_digits(char number[100]) {
int size = sizeof(number[100]);
for (int i = 0; i < size; i++) {
if (number[i] % 2 == 1) {
printf("%d\n", number[i]);
}
}
return 0;
}
int main(void) {
print_odd_digits("1234");
}

sizeof(number[100]) is equivalent to sizeof(char), which is 1. What you want seems strlen(number).
Elements of number are not values of digits but character codes of digits. To convert number characters to values, you can subtract '0'. (character codes for 0 to 9 are defined to be continuous in C).
%d is for printing integer and 49 is ASCII code for the character 1. Use %c to print character corresponding to passed integer.
You may want newline only on end of the characters.
Try this:
#include <stdio.h>
#include <string.h> /* for using strlen() */
int print_odd_digits(char number[100]) {
int size = strlen(number);
for(int i = 0; i < size; i++){
if((number[i] - '0') % 2 == 1){
printf("%c",number[i]);
}
}
printf("\n");
return 0;
}
int main(void) {
print_odd_digits("1234");
}

You have a type error here. You are working with the ascii codes for the text characters for digits. You need to use the atoi(char* str)
function to convert the digits to a corresponding number and use math to determine a particular digit or loop over the characters and subtract -'0' the ascii code for the digit zero as digits are sequential.
#include <stdlib.h>
#include <stdio.h>
int main() {
char* digit_one_str = "1";
char digit_9 = '9';
printf("digit one ascii value: %d\n", digit_one_str[0]); // first char in string digit one
int number_one = atoi(digit_one_str);
printf("digit one parsed from sttring by atoi: %d\n", number_one);
printf("digit 9 as char converted with -'0' trick: %d", (int)(digit_9 - '0'));
}
Further it is better practice to take in a char* and a length than to work with fixed sized arrays or using strlen() where you don't actually have to. In C a string ends in a terminating '\0' character which might not even be present if the code calling your function is buggy or malicious.

Related

How to write a function that receives a string as a parameter and returns the maximum digit that appears in the string?

These are the details. (https://i.stack.imgur.com/cMY9J.png)
#include <stdio.h>
#include <stdlib.h>
int maxdigit(char sir[]);
int main()
{
char s[100];
gets(s);
printf("The greatest digits is %i\n", maxdigit(s));
}
int maxdigit(char sir[])
{
int i, max = 0;
for(i=0;i<100;i++)
{
if(max<sir[i])
{
max = sir[i];
}
}
return max;
}
I genuinely don't know how to get only the integer values in a string to return it. How can i do it so it doesn't compare with the ascii codes of the letters?
A few problems here:
gets() is a dangerous function (since it can lead to buffer overflows), and has been removed from the C standard. Consider using fgets() or scanf().
Your code assumes that all 100 digits have been entered by the user. If they enter less than 100, the memory for the other digits is uninitialised, and will probably be full of garbage. You need to stop when you reach the '\0' that terminates the string.
To convert an ASCII code (for a digit) to the value of the digit, subtract '0' from it. But you'll need to ensure that all the entered digits are actually digits, maybe with isdigit().
Iterate until null terminating character. In your code you go beyond end of the string if the string length is smaller than the array
Convert char representation of the digit to its integer value by substracting 0.
unsigned maxdigit(const char *str)
{
unsigned max = 0;
if(str)
{
while(*str)
{
if(isdigit((unsigned char)*str))
{
if(max < *str - '0') max = *str - '0';
}
str++;
}
}
return max;
}

Why does this final.exe file execute in an infinite loop instead of the specified number as below?

final.exe file.
this executes infinitely or up to 50.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
if (argc < 2)
{
printf("ERROR: You need at least one argument.\n");
return 1;
}
else
{
int i, j;
for(i=1;i<=(int)*argv[1];i++)
{
printf("\n");
(void)system("test1.exe");
}
}
}
test.c file contains :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
printf("Hello World");
}
Expected - For ex. : ./final 2 : The output should be Hello World Hello World , i.e, prints only 2 times and not infinitely.
(int)*argv[1] is using the character code of the first character as the number of iteration. Character codes are usually differ from the number that the character represents.
To convert a string to corresponding number, you can use atoi() (if you don't care about invalid input).
int i, j;
int num = atoi(argv[1]);
for(i=1;i<=num;i++)
{
printf("\n");
(void)system("test1.exe");
}
for(i=1;i<=(int)*argv[1];i++)
The expression (int)*argv[1] uses the first character of the first command line argument (not counting the program name) as a number. That is, assuming an ASCII-like or Unicode-like encoding, the character 0 is treated as value 48, 1 as 49, ..., and 9 as 57. The (int) doesn't really make a difference.
If you really want to use just that first character, you could do something like
if (isdigit(*argv[1])) {
int count = *argv[1] - '0'; // works with any encoding
Or to allow multi-digit counts, you could do something like
char *parse_end;
int count = strtol(argv[1], &parse_end, 10);
if (parse_end != argv[1] && *parse_end == '\0' && count >= 0) {

can't use sscanf() in C for char array

I'm trying to get a very large number (more than unsigned long long int). So I get it as a string and then convert it, digit by digit, into integer and use it.
#include <stdio.h>
#include <string.h>
int main()
{
char m[100];
int x;
scanf("%s",m);
for(int i=0; i<strlen(m); i++){
sscanf(m[i],"%d",&x);
printf("%d",x);
}
return 0;
}
However, during compiling it shows:
warning: passing argument 1 of ‘sscanf’ makes pointer from integer
without a cast
and
note: expected ‘const char * restrict’ but argument is of type ‘char’
And, when I run program it will give me the Segmentation fault (core dumped) error.
I also tried more simple code to find the problem:
#include <stdio.h>
#include <string.h>
int main()
{
char m[5];
char n;
int x;
scanf("%s",m);
n = m[1];
sscanf(n,"%d",&x);
return 0;
}
but nothing changed.
scanf doesn't apply to characters. Once you have the characters just convert digits to integers by subtracting '0' as a char:
for(int i=0; i<strlen(m); i++){
x = m[i] - '0'; // line to change
printf("%d",x);
}
Besides, just to make sure that the buffer won't overflow, 100 bytes is good, but you may want to use an according limit in scanf and check the return code:
if (scanf("%99s",m) == 1) {
Using sscanf to convert a single digit of a character string to an integer is the wrong approach. To do this, you only need to subtract the (integer) value of the representation of the character '0' from that digit. Like this:
#include <stdio.h>
#include <string.h>
int main()
{
char m[50]; // As pointed out, a 4-digit number isn't really very long, so let's make it bigger
int x;
scanf("%49s", m); // Limit the input to the length of the buffer!
for (size_t i = 0; i < strlen(m); i++) { // The "strlen" function return "size_t"
x = m[i] - '0'; // The characters `0` thru `9` are GUARANTEED to be sequential!
printf("%d", x);
}
return 0;
}

I mixed up two programs in the cs50 sandbox in c?

I mixed up two programs in the cs50 sandbox, one was to find the the number of characters in an array and other was the print these characters. I know the program is garbage but could anyone explain me what is the compiler doing here?
When I ran this, the output starts printing alphanumeric text and never stops Thanks
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
int n = 0;
while (strlen(s) != '\0')
{
n++;
printf("%c", n);
}
}
You have multiple problems with the code you show, here's a couple of them:
strlen(s) will never be zero as you never modify or remove characters from the string, which means you have an infinite loop
n is an integer and not a character so should be printed with the %d format specifier
'\0' is (semantically) a character, representing the string terminator, it's not (semantically) the value 0
To fix the first problem I suspect you want to iterate over every character in the string? Then that could be done with e.g.
for (int i = 0; i < strlen(s); ++i)
{
printf("Current character is '%c'\n", s[i]);
}
But if all you want is to could the number of characters in the string, then that's what strlen is already gives you:
printf("The number of characters in the string is %zu\n", strlen(s));
If you want to count the length of the string without using strlen then you need to modify the loop to loop until you hit the terminator:
for (n = 0; s[n] != '\0'; ++n)
{
// Empty
}
// Here the value of n is the number of characters in the string s
All of this should be easy to figure out by reading any decent beginners book.
while (strlen(s) != '\0') is wrong. '\0' equals 0. There string length is never 0, so the loop keeps going on forever, printing integers interpreted as characters.
You can either use the indexes to go through the string characters by using the variable "n" or you can increment the pointer of the string that you have received from the standard input to go through all of its characters.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
/* First way using n to iterate */
int n = 0;
for (n = 0; n < strlen(s); ++n)
{
printf("%c", s[n]);
}
printf("\n");
/* Second way increment the string pointer*/
while (strlen(s) != '\0')
{
printf("%c", *s); //print the value of s
s++; // go to the next character from s
}
printf("\n");
return 0;
}

Converting user input to an array of characters, and filtering letters from other characters?

#include "stdafx.h"
#include "stdlib.h"
#include <ctype.h>
int num = 0;
int i = 0;
int ch = 0;
int letter_index_in_alphabet(int ch) {
if (isalpha(ch) == true) {
char temp_str[2] = { ch };
num = strtol(temp_str, NULL, 36) - 9;
printf("%d is a letter, with %d as its location in the alphabet!", ch, num);
}
else {
return -1;
}
}
int main()
{
char input_str[10];
printf("Please enter a series of up to 10 letters and numbers: \n");
fgets(input_str, 10, stdin);
for (i == 0; i <= 10; i++) {
ch = input_str[i];
letter_index_in_alphabet(ch);
}
return 0;
}
Hello everyone, this is my first post on SOF! The goal of this program is to read characters from the standard input to EOF. For each character, report if it is a letter. If it is a letter, print out its respective index in the alphabet ('a' or 'A' = 1, 'b' or 'B' = 2..etc). I have been searching some other posts on stackoverflow and this has helped me get this far(using fgets and strtol functions). I have no visible syntax errors when I run this code, but after I enter a string of characters (ex: 567gh3fr) the program crashes.
Basically, I am trying to use 'fgets' to bring each character entered into a string with the appropriate index. Once I have that string, I check each index for a letter and if it is, I print the number assigned to that letter of the alphabet.
Any help or insight into why this isn't working as intended is greatly appreciated, Thanks!
You have a few problems.
First, char input_str[10] is only big enough for the user to enter 9 characters, not 10, because you need to allow one character for the null byte that ends a string.
Second, your loop goes too far. For a string with 10 characters, indexes go up to 9, not 10. It also should stop when it gets to the null byte, since the user might not have entered all 9 characters.
To get the position in the alphabet, you can simply subtract the value of A or a from the value of the character. Use tolower() or toupper() to convert the character to the case that you're going to use. Your method works, but it's overly complicated and confusing.
letter_index_in_alphabet() is declared to return int. But when the character is a letter, it doesn't execute a return statement. I'm not sure why it's supposed to return something, since you never use the return value, but I've changed it to return the position (maybe the caller should be the one that prints the message, so the function just does the calculation).
In the for loop, it should be i = 0 to perform an assignment, not i == 0 which is comparison.
You also shouldn't use global variables so much. And system header files should have <> around them, not "".
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int letter_index_in_alphabet(int ch) {
if (isalpha(ch)) {
int num = tolower(ch) - 'a' + 1;
printf("%d is a letter, with %d as its location in the alphabet!\n", ch, num);
return num;
} else {
return -1;
}
}
int main()
{
char input_str[10];
printf("Please enter a series of up to 9 letters and numbers: \n");
fgets(input_str, sizeof(input_str), stdin);
for (int i = 0; input_str[i]; i++) {
letter_index_in_alphabet(input_str[i]);
}
return 0;
}

Resources