I am trying to learn programming and am doing some random questions and tasks. The task is to write out the last three characters of a string and this is what I've come up with. Please do not solve this for me, I am asking about my output/result not for anyone to do the problem solving for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int func(char *input_1, char *input_2) {
char last_three_digits_1[3]; // define two arrays that hold the last three characters
char last_three_digits_2[3];
int x = 0;
for(int y = strlen(input_1) - 4; y < strlen(input_1) - 1; y++) {
last_three_digits_1[x] = input_1[i];
x++;
}
x = 0; // repeat for the second string
for(int z = strlen(input_2) - 4; z < strlen(input_2) - 1; z++) {
last_three_digits_2[x] = input_2[i];
x++;
}
printf("last3_1: %s, \nlast3_2: %s\n", last_three1, last_three2); // this seem to access random memory because it outputs "abc" followed by random "-???" or "-????" or "-?2?2". Same for the second array.
return 0;
}
int main(int argc, char * argv[] ) {
if(argc == 3) { // needs to be two strings. E.g: "abcd efghi"
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3) { // if any of the strings are less than 3 in length, e.g. "ab wadnkwa" then do not proceed.
func(argv[1], argv[2]); // send the user input to the function
}
return 0; // maybe redundant
}
return 0; // return 0 for failure
}
The condition in the if statement
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3)
means that the length of one of the strings can be less than 3. In this case the function func can invoke undefined behavior.
It seems you mean
if(strlen(argv[1]) >= 3 && strlen(argv[2]) >= 3)
Otherwise you need in the function func to make a check whether a string has length greater than or equal to 3 before outputting its last three characters.
If a string has exactly three characters then for example in this loop
for(int i = strlen(text1) - 4; i < strlen(text1) - 1; i++)
the variable i can have an implementation defined value as for example -1 and as a result this expression text1[i] invokes undefined behavior.
The return type int of the function does not have a meaning.
Pay attention to that if you are using the format %s to output a character array using printf then the array shall contain a string that is a sequence of characters terminated with the zero character '\0'.
So neither the if statement in main nor the function itself makes a sense.
To output last three (or any other number) characters of a string there is no need to create an auxiliary array. It can be done much simpler.
For example
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if ( !( n1 < n ) ) text1 += n1 - n;
size_t n2 = strlen( text2 );
if ( !( n2 < n ) ) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
And the function can be called like
func( argv[1], argv[2], 3 );
Using such a declaration of the function you can output any number of last characters of two strings. Also take into account that the function parameters have the qualifier const because the passed strings are not changed within the function.
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if (!( n1 < n )) text1 += n1 - n;
size_t n2 = strlen( text2 );
if (!( n2 < n )) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
int main( void )
{
func( "Hello", "World", 3 );
}
The program output is
last3_1: llo,
last3_2: rld
char last_three1[3]; // define two arrays that hold the last three characters
char last_three2[3];
You need space to hold \0 char, because %s expects char* to be \0 terminated.
char last_three1[4];
char last_three2[4];
….
last_three1[x] = '\0';
x = 0; // repeat for the second string
for(int i = strlen(text2) - 4; i < strlen(text2) - 1; i++) {
last_three2[x] = text2[i];
x++;
}
last_three2[x] = '\0';
Strings in C are terminated with a single zero byte.
You're not zero-terminating the strings, so printf doesn't know where to stop printing (and you're lucky your program doesn't outright crash).
I'd refactor things like this, so you have a single function that simply copies the three last bytes and zero-terminates the string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// out must be an array that can hold 4 bytes
// in must be >= 3 characters; otherwise this function returns non-zero
int get_last_three(char *out, const char *in) {
int len = strlen(in);
if (len < 3)
return -1;
for (int i = len - 3; i < len; i++) {
*out = in[i];
out++;
}
*out = 0; // Zero-terminate
return 0;
}
int main(int argc, char *argv[]) {
char out[4];
for (int i = 1; i < argc; i++) {
if (get_last_three(out, argv[i]) == 0) {
printf("last3_%d: %s\n", i, out);
}
}
}
Related
I have a problem with the return of that function, it should return the vector with the typed sequence, but it's returning an ordered sequence, could you tell me where I'm going wrong?
Create a recursive function that takes a string as input and also its length. This function should return how many times the character the substring “hi” appears in the string.
Prohibited
The first line in the input contains the number n of test cases. Next, n lines occur, each containing a string of maximum length equal to 5000 characters
Exit
The output consists of n lines, each containing an integer that indicates the number of times the string “hi” occurs in the input string. All strings are written in lowercase letters.
Example
Prohibited
4
hipotenuse hipothermia hilux hifi
hi
hihihi
xavante hey
Exit
4
1
3
0
My code:
#include <stdio.h>
#include <string.h>
#define MAX 5000
int ocorrencias(const char *palavra, size_t len) {
char *st = "hi";
return len ?
(*st == *palavra) + ocorrencias(palavra + 1, len - 1) :
0;
}
int main() {
int n,i;
scanf("%d",&n);
char palavra[MAX];
int re[n];
for(i=0; i<=n; i++){
fgets(palavra, MAX, stdin);
re[i] = ocorrencias(palavra, strlen(palavra));
}
for(i=0; i<=n; i++){
printf("%d\n", re[i]);
}
}
For starters the for loops like this
for(i=0; i<=n; i++){
^^^^^
are wrong.
You need to write
for(i=0; i < n; i++){
^^^^^^
The function ocorrencias should be declared either like
size_t ocorrencias( const char *palavra );
or like
size_t ocorrencias( const char *palavra, const char *st );
instead of
int ocorrencias(const char *palavra, size_t len) ;
because it deals with strings and the function is able to determine lengths of passed strings.
It can be defined for example the following way
size_t ocorrencias( const char *palavra )
{
const char *st = "hi";
const char *p = strstr( palavra, st );
return p == NULL ? 0 : 1 + ocorrencias( p + strlen( st ) );
}
So in main you should write
size_t re[n];
//...
for ( i = 0; i < n; i++ )
{
printf( "%zu\n", re[i] );
}
Otherwise if you want to count substrings either "hi" or "hy" (according to your comment to the question) then the function can look the following way
size_t ocorrencias( const char *palavra )
{
const char *p = strchr( palavra, 'h' );
return p == NULL ? 0 : ( p[1] == 'i' || p[1] == 'y' ) + ocorrencias( p + 1 );
}
The task is:
Write a full program that takes an int n > 0 and recursively prints all combinations of characters 'a' and 'b' on the screen.
Example for n=3: aaa, baa, bba, aba, bab, aab, abb, bbb.
I assume I have to use something similar to Backtracking.
This is what I have, but Im not able to think of the rest.
void rep(int n, char str, int pos) { //n would be the length and str would be the pointer
char c[n + 1];
char d[3];
d[0] = 'a';
d[1] = 'b';
for (int j = 0; j < 2; j++) {
if (strlen(c) == n) { // if c is n long recursion ends
printf("%s", c);
} else {
c[pos] = d[j]; // put 'a' or 'b' in c[pos]
rep(n, c, pos + 1); // update pos to next position
}
}
}
The variable length array c is not initialized
char c[n+1]
Thus the call of strlen in this if statement
if(strlen(c) == n){
invokes undefined behavior.
Moreover the parameter str is not used within the function.
I can suggest the following solution as it is shown in the demonstration program below
#include <stdio.h>
#include <string.h>
void rep( char *s )
{
puts( s );
char *p = strchr( s, 'a' );
if (p != NULL)
{
memset( s, 'a', p - s );
*p = 'b';
rep( s );
}
}
int main()
{
char s[] = "aaa";
rep( s );
}
The program output is
aaa
baa
aba
bba
aab
bab
abb
bbb
That is the function rep is initially called with an array that contains a string of the required size n (in the demonstration program n is equal to 3) consisting of all characters equal to the character 'a' and recursively outputs all combinations until the string contains all characters equal to the character 'b'.
There a some issues in your code:
the str argument should have type char *
you so not need new arrays in the recursive function, but use the one the str argument points to.
you do not set a null terminator at the end of your char arrays.
instead of strlen(), use pos to determine if the recursion should stop.
Here is a modified version
#include <stdio.h>
// n is the length and str points to an array of length n+1
void rep(int n, char *str, int pos) {
if (pos >= n) {
str[n] = '\0'; // set the null terminator
printf("%s\n", str);
} else {
str[pos] = 'a';
rep(n, str, pos + 1);
str[pos] = 'b';
rep(n, str, pos + 1);
}
}
#define LEN 3
int main() {
char array[LEN + 1];
rep(LEN, array, 0);
return 0;
}
I am really new to C and in my first half year at university. This is my first questio on StackOverflow.
My task is to program it so every string stored in numbers is being converted into a decimal, without changing anything outside the main function.
I am now trying for the past 4 hours to solve this problem, where I want to iterate trough every char in the string I am currently to then, based on there position in comparison to the length to convert it into a decimal.
My only question here is to someone help me to understand how I can get the string length without using strlen() due to the fact I can't add #include <string.h>
This is what I got so far (getting the length of the array to iterate through every index):
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
int length = sizeof(numbers);
for ( int i = 0; i < length; i++ ){
//how do i get the string size without strlen() D:
}
return 0;
}
In C, strings are really just char arrays with a special terminator character to mark the end of the string. So, say you have something like:
char *str = "hello";
This is essentially equivalent to this:
char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};
Notice that \0 character at the end of the array? This is the special terminator character that C places at the end of strings. Functions like strlen() pretty much iterate through the char array looking for the first occurrence of the \0 character and then stopping.
So, you can make your own version of strlen(), say my_strlen() like this:
int my_strlen(char *str)
{
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
Then within your for loop, you can just call this function. Also, note that your calculation of the size of the numbers array:
int length = sizeof(numbers);
will not give you the number of elements in the array. That code gives you the size (in bytes) or numbers which is an array of char pointers. If you want to get the number of elements, you have to divide that size by the size (in bytes) of a single element (i.e., a char pointer). So, something like this would work:
int length = sizeof(numbers) / sizeof(numbers[0]);
Your final code can look something like this:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int my_strlen(char *str) {
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
// Notice the change here
int length = sizeof(numbers) / sizeof(numbers[0]);
for(int i = 0; i < length; i++ ){
int str_len = my_strlen(numbers[i]);
// Do what you need with str_len
}
return 0;
}
This project can be done without computing the length of the strings. How? In C, all strings are nul-terminated containing the nul-character '\0' (with ASCII value 0) after the last character that makes up the string. When you need to iterate over a string, you just loop until the character values is 0 (e.g. the nul-character)
This is how all string function know when to stop reading characters. Since you have an array-of-pointers that contains your strings, you just need to loop over each pointer and for each pointer, loop over each character until the nul-character is found.
Putting it altogether, (and noting you don't need math.h), you can do:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
int nnumbers = sizeof numbers / sizeof *numbers; /* no. of elements */
for (int i = 0; i < nnumbers; i++) {
long long unsigned number = 0;
/* you don't care about the length, strings are nul-terminated,
* just loop until \0 is found.
*/
for (int j = 0; numbers[i][j]; j++) {
number <<= 1; /* shift left */
number += numbers[i][j] == '1' ? 1 : 0; /* add bit */
}
printf ("%s = %llu\n", numbers[i], number); /* output result */
}
return 0;
}
(note: you must use a 64-bit type to hold the converted values as "1010110011010101111101111010101110110" requires a minimum of 38 bits to represent)
Example Use/Output
Simple example output converting each string to a numeric value:
$ ./bin/binstr2num
01001001 = 73
00101010 = 42
010100111001 = 1337
011111110100101010010111 = 8342167
0001010110011010101111101111010101110110 = 92790519158
01011100110000001101 = 379917
#include <stdio.h>
int main(){
char arr[20]="Hello";
int count=0;
while(arr[count]!='\0'){
count++;
}
printf("%d",count);
return 0;
}
Look at this small code, you will understand. In C a string ended with a NULL character. We can use that advantage.
There are a few ways to do it. IMO, a simple, reasonable way to implement strlen is:
size_t string_length(const char *s) { return strchr(s, '\0') - s; }
but if you're not allowed to use strlen then you're probably not allowed to use strchr either. So you just have to count. The most idiomatic way to do that is probably a bit obscure for a complete beginner, so here is a more verbose method.
Note that your computation of the number of elements in the array is invalid, and has been corrected below.
#include <stdio.h>
int
length(const char *s)
{
int len = 0;
while( *s++ ){
len += 1;
}
return len;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
int count = sizeof numbers / sizeof *numbers; /* Number of entries */
for( int i = 0; i < count; i++ ){
printf(" length of %s is %d\n", numbers[i], length(numbers[i]));
}
return 0;
}
It's pretty subjective, but IMO a more idiomatic way to write this is:
#include <stdio.h>
int
length(const char *e)
{
const char *s = e;
while( *e++ )
;
return e - s - 1;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
char **e = numbers + sizeof numbers / sizeof *numbers;
for( char **t = numbers; t < e; t++ ){
printf(" length of %s is %d\n", *t, length(*t));
}
return 0;
}
I have a problem that goes:
Create a C program that inputs large integers as strings.
Then every character is converted into the corresponding digit.
After that I have to create a function addBigNumbers() that has 3 matrices.
addBigNumbers(char *a1, char *a2, char *res)
a1 and a2 will contain the 2 large numbers that I want to add,res will contain the sum of those as a number sequence. We want the function that we created to check if the strings contains numbers only.
If it contains only numbers then res equals 1 and it prints the sum of those numbers else res is equal to 0 (max number length is 1000)
After that first function we want to create a function for subtraction.
So far I haven't gotten to subtraction since I stuck in the first one and I need your help.
This is the code that I have so far:
#include <stdio.h>
#include <stdlib.h>
#define N 1000
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int addHugeNumbers(char *a1, char *a2, char *res){
int y=0, u=0, h=0;
res=strcat(a1,a2);
if(strlen(a1)>strlen(a2)){
y=atoi(a1);
u=atoi(a2);
h=y+u;
}
else{
y=atoi(a1);
u=atoi(a2);
h=u+y;
}
printf("%d", h);
}
int main(int argc, char *argv[]) {
char res[N];
char a1[N/2];
char a2[N/2];
scanf("%s", &a1);
scanf("%s", &a2);
addHugeNumbers(a1, a2, res);
return 0;
}
The problem I have is that if I input ex. 23 23 it outputs 2346 which is obviously wrong but it got 46 correct, when I input 1234 123 it outputs 1234246 which is all wrong.
Where it gets weird is if i input something like 1234r 123 or anything else that has a character in it, it outputs the exact sum.
The problem is res=strcat(a1,a2), which does something very different than that what you think: it appends a2 to a1, and it does not "create" a new string. See, for example strcat-definition at cppreference.com:
char *strcat( char *dest, const char *src )
Appends a copy of the null-terminated byte string pointed to by src
to the end of the null-terminated byte string pointed to by dest. The
character src[0] replaces the null terminator at the end of dest. The
resulting byte string is null-terminated.
So you are manipulating your input before calculating something, and that's what you will observe then when using a debugger.
Further, scanf("%s", &a1) looks suspicious; it should be scanf("%s", a1);. Your compiler should have warned you.
You'd probably rethink addBigNumbers, probably adding the digits in a loop rather than converting them to (somehow always) limited integral data types in between. This task is actually nothing for beginners in C; take the following fragment to study:
#define N 1000
int addHugeNumbers(char *a1, char *a2, char *res){
char resultBuffer[N];
int i1 = (int)strlen(a1);
int i2 = (int)strlen(a2);
int carryOver = 0;
int ri = 0;
while (i1 > 0 || i2 > 0) { // until both inputs have been read to their beginning
i1--;
i2--;
// read single digits and consider that a string might have already
// been read to its beginning
int d1 = i1 >= 0 ? a1[i1] - '0' : 0;
int d2 = i2 >= 0 ? a2[i2] - '0' : 0;
// check for invalid input
if (d1 < 0 || d1 > 9 || d2 < 0 || d2 > 9) {
return 0;
}
// calculate result digit, taking previous carryOver into account
int digitSum = d1 + d2 + carryOver;
carryOver = digitSum / 10;
digitSum %= 10;
resultBuffer[ri++] = digitSum + '0';
}
// write the last carryOver, if any
if (carryOver > 0) {
resultBuffer[ri++] = carryOver + '0';
}
// copy resultBuffer into res in reverse order:
while(ri--) {
*res++ = resultBuffer[ri];
}
// terminate res-string
*res = '\0';
return 1;
}
int main(int argc, char *argv[]) {
char res[N];
char a1[N/2] = "123412341234";
char a2[N/2] = "1231";
if (addHugeNumbers(a1, a2, res)) {
printf("result: %s\n", res);
} else {
printf("invalid number.\n");
}
return 0;
}
My program grabs command line arguements with argc and argv[]. My question is how can I find the length of argv[1][i].
My code that grabs length of argv[]
int my_strlen(char input[]){
int len = 0;
while(input[len] != '\0'){
++len;
}
return len;
}
but when I try to find argv[1][len] I get a subscripted value is neither array nor pointer:
my attempt
int my_strlen(char input[]){
int len = 0;
while((input[1][len] - '0') != '\0'){
++len;
}
return len;
}
FULL CODE:
#include <stdio.h>
#include <math.h>
int my_strlen(char input[]);
int main(int argc, char *argv[]){
int length = 0;
length = my_strlen(argv[1]);
long numberArr[length];
int i, j;
for(i = 0; i < length; i++){
numberArr[i] = argv[1][i] - '0';
}
return 0;
}
int my_strlen(char input[]){
int len = 0;
while((input[1][len] - '0') != '\0'){
++len;
}
return len;
}
Thanks for any help in advance!
I think you're confused about the argv content. The OS will pass a number of ASCIIZ strings, such that invoking my_program with arguments ala...
my_program first second third
...is similar to having the following declaration in your program...
int argc = 4;
const char* argv[4] = { "my_program", "first", "second", "third" };
Hence, when you index into argv[1][i] you're getting the i-th character in the string "first". That's only valid for values of i between 0 (which yields 'f'), and 5 (which indexes to the terminating NUL character '\0').
So, there no two-dimensional N*M array, but there is an array of pointers-to-(array-of-char). You can invoke the normal strlen() function as in strlen(argv[1]) to find out the number of characters in each argument. Only argc tells you the total number of elements in argv.
Does that help?
In main, you're passing argv[1] to my_strlen. That means my_strlen just receives a normal, single-dimension string. It doesn't need to do input[1][len], just input[len].