c言語あれこれ

8 min read読了の目安(約7600字

逐次追加していくタイプの記事

文字列のあれこれ

#include <stdio.h>
#include <string.h>
int main(void) {
	char t[20] = "ABCDEFGHIJK";

	t[3] = '\0';
	printf("%s",t); // ABCのみを表示

	strcpy(t1, t); // コピー
	printf("%s\n", t1);
	printf("%lu", strlen(t1)); // 長さ

return 0;
}

文字列の入力

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int n, i;
    char *ptr;

    printf("Enter number of characters to store: ");
    scanf("%d", &n);

    ptr = (char*)malloc(n*sizeof(char));

    for(i=0; i < n; i++)
    {
        printf("Enter ptr[%d]: ", i);
        /* notice the space preceding %c is
          necessary to read all whitespace in the input buffer
        */
        scanf(" %c", ptr+i); 
    }

    printf("\nPrinting elements of 1-D array: \n\n");

    for(i = 0; i < n; i++)
    {
        printf("%c ", ptr[i]);
    }

    // signal to operating system program ran fine
    return 0;
}

文字列のポインタ

#include <stdio.h>
#include <string.h>

int main () {
    // https://dixq.net/forum/viewtopic.php?t=11845
    const char* message = "abcdef"; // 文字列のポインタ
    printf("%s\n", message); // agcdef
    printf("%d\n", strlen(message)); // 6

    int m=0;
    while(message[m] != '\0'){
        printf("%c\n", message[m]);
        m++;
    }

    const char* message_pointer = message;
    while(*message_pointer != '\0'){ // 文字
        printf("%c\n", *message_pointer);
        message_pointer++;
    }

参考

Difference between char* and const char*?

https://stackoverflow.com/questions/9834067/difference-between-char-and-const-char

文字列の初期化

以下のコードの違い

char arr[] = "Hello World"; // array version
char ptr* = "Hello World";  // pointer version

上は、Hello Worldの文字列12文字分のスペース12byteをメモリ上に確保。
下は、Hello Worldの文字列12文字分のスペース12byteとその文字列の先頭を指すポインタ4byteの合計16byteをメモリ上に確保

ポインタのポインタ

#include <stdio.h>

int main () {
    int num = 12;
    int *p_num = &num;
    int **pp_num = &p_num;
    
    printf("num: %d, &num: %p\n", num, &num);
    printf("p_num: %p, *p_num: %d, &p_num: %p\n", p_num, *p_num, &p_num);
    printf("pp_num: %p, *pp_num: %p, **pp_num: %d\n", pp_num, *pp_num, **pp_num);
}
um: 12, &num: 0x7ffee3a8d564
p_num: 0x7ffee3a8d564, *p_num: 12, &p_num: 0x7ffee3a8d558
pp_num: 0x7ffee3a8d558, *pp_num: 0x7ffee3a8d564, **pp_num: 12

動的メモリ管理

#include<stdio.h>
#include <stdlib.h>
#include <string.h>

int size = 10;

struct Student{
    char name[30];
};

struct Student** students;

int main(){
    students = (struct Student **)malloc(size*sizeof(struct Student *));

    for(int i=0; i<size; i++){
        students[i] = (struct Student *)malloc(sizeof(struct Student));
        char name1[30];
        sprintf(name1, "john %d", i+1);
        strcpy(students[i]->name, name1);
    }

    for(int i=0; i<size; i++){
        printf("%s\n", students[i]->name);
    }

    for(int i=0; i<size; i++){
        free(students[i]);
    }
    free(students);

    return 0;
}

関数の引数でポインタのポインタ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// ポインタ変数のアドレスを受け取るのでダブルポインタ(ポインタのポインタ)
int memory_alloc( char ** pptr, char * contents ) {

  *pptr = malloc( strlen( contents ) + 1 );
  if( *pptr == NULL ) {
    return -1;
  }

  memset( *pptr , '\0' , strlen( contents ) + 1 );
  strcpy( *pptr , contents );

  return 0;
}

main() {

  char * ptr;
  int ret;

  ret = memory_alloc( &ptr, "テストデータ" ); // ptrのアドレスを渡す。参照渡し
  if( ret == -1 ) {
    printf( "メモリ確保エラー\n" );
    return -1;
  }

  printf( "ptr=%s\n" , ptr );

  free( ptr );/* メモリ開放 */
}

http://hitorilife.com/pointerofpointer.php

配列

#include <stdio.h> 
 
void incvec(int *const vec, int len){ 
	for(int i=0; i<len; ++i) vec[i]+=i; 
} 
void addscalar(int *const vec, int len, int val){ 
	for(int i=0; i<len; ++i) vec[i] += val; 
} 
void setvec(int *const vec, int len, int val){ 
	for(int i=0; i<len; ++i) vec[i]=val; 
} 
void printvec(const int *const vec, int len){ 
	for(int i=0; i<len; ++i) printf("%2d ", vec[i]); 
	putchar('\n'); 
} 
 
#define LEN 10 
int main(){ 
	int vector[LEN]; 
 
	setvec(vector, LEN, 0); 
	printvec(vector, LEN); 
 
	incvec(vector, LEN); 
	printvec(vector, LEN); 
 
	addscalar(vector, LEN, 2); 
	printvec(vector, LEN); 
 
} 

ref. https://www.quora.com/How-can-I-change-the-values-of-an-array-with-a-void-function-in-c

2次元文字列配列

#include <stdio.h>

void function(int n, int m, char array[][5]) {
    // printf("%p\n", array);

    for(int i=0; i< n; i++){
        printf("%s\n", *(array+i));
    }
}

int main() {
    char array[3][5] = {"asdf", "bfds", "1111"};
    // printf("%p\n", array);
    function(3,5,array);
}
asdf
bfds
1111

https://stackoverflow.com/questions/31620577/pass-a-2d-char-array-to-a-function-in-c

mallocと関数ポインタの例

2つベクトルのサイズ、値を入力させて、そのscalar productを計算する

#include <stdio.h>
#include <stdlib.h>

// Write a program to calculate the scalar product of two vectors.

int* create_array(int size){
    int *arr=NULL;
    arr=(int*)malloc(size*sizeof(int));

    for(int i=0;i<size;i++){
        scanf("%d", arr+i);
    }
    return arr;
}

int main() {

    int size;
    printf("Enter size: ");
    scanf("%d", &size);

    int *vector1=NULL;
    int *vector2=NULL;

    printf("Enter elements of the 1st vector: \n");
    vector1 = create_array(size);
    printf("Enter elements of the 2nd vector: \n");
    vector2 = create_array(size);

    int sum=0;

    for(int i=0;i<size;i++){
        sum=sum + vector1[i]*vector2[i];
    }
    printf("scalar product: %d\n", sum);

    int newsize;
    printf("Enter a new size:");
    scanf("%d", &newsize);

    vector1=realloc(vector1,newsize*sizeof(int));
    vector2=realloc(vector2,newsize*sizeof(int));


    printf("Enter elements of the 1st vector again: \n");
    vector1 = create_array(newsize);

    printf("Enter elements of the 2nd vector again: \n");
    vector2 = create_array(newsize);

    sum =0;
    for(int i=0;i<newsize;i++){
        sum=sum + vector1[i]*vector2[i];
    }
    printf("scalar product: %d\n", sum);

    return 0;
}

charとstringの違い

character is just a single character enclosed in single quotes. For example:

char initial = 'A'; /* initial declared to be a character */

And a character string is a sequence of 0 or more characters enclosed in double quotes. Each string is terminated by a NULL byte. Therefore, string containing 0 characters is called an empty string.
https://www.sanfoundry.com/c-tutorials-difference-between-character-string/

Linusがしていたポインターの話

https://grisha.org/blog/2013/04/02/linus-on-understanding-pointers/

What is the difference between char array and char pointer in C?

日本語の記事

char a[] = "abc";
char *b = "abc";
printf("%s %s\n", a, b);  // abc abc

この二つには大きな違いがあります。
char amsg[]: char型の変数を4個実際に確保。その中に'a', 'b', 'c', '\0'を入れる。これらは普通の配列なので、自由にアクセス・変更できる。

char *pmsg: char型ポインタを1個だけ確保。プログラムのどこかで文字列リテラル"abcd"が確保される。そのリテラルのアドレスが入る。リテラルなので、アクセスは出来るが変更は出来ない。

https://eeic-software1.github.io/2020/week4/#_15

why strchr() having "int" as second parameter.

https://stackoverflow.com/questions/2394011/why-does-strchr-take-an-int-for-the-char-to-be-found

参考