- 左操作數是一個指向有const限定符的char的指針 (const是用來修飾char類型的,並不是修飾*指針類型的)
- 右操作數是一個指向沒有限定符的char的指針
- char類型與char類型是相容的,左操作數所指向的類型具有右操作數所指向類型的限定符(其實沒有),在加上自身的限定符(const)
fprintf(stderr, "-1 < (unsigned int)1)\n");
} else {
fprintf(stderr, "-1 > (unsigned int)1)\n");
}
if (-1 < (unsigned char)1) {
fprintf(stderr, "-1 < (unsigned char)1)\n");
} else {
fprintf(stderr, "-1 > (unsigned char)1)\n");
}
-1 < (unsigned char)1) // -1類型不動,仍然是int類型,(unsigned char)1被提升到int類型
int b[] = {3, 4};
array ab = {&a, &b};
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum type_tag { IDENTIFIER, QUALIFIER, TYPE };
struct token {
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token this;
#define pop stack[top--]
#define push(s) stack[++top] = s
enum type_tag classify_string()
{
char* s = this.string;
if (!strcmp(s, "const")) {
strcpy(s, "read-only");
return QUALIFIER;
}
if (!strcmp(s, "volatile")) return QUALIFIER;
if (!strcmp(s, "void")) return TYPE;
if (!strcmp(s, "char")) return TYPE;
if (!strcmp(s, "signed")) return TYPE;
if (!strcmp(s, "unsigned")) return TYPE;
if (!strcmp(s, "short")) return TYPE;
if (!strcmp(s, "int")) return TYPE;
if (!strcmp(s, "long")) return TYPE;
if (!strcmp(s, "float")) return TYPE;
if (!strcmp(s, "double")) return TYPE;
if (!strcmp(s, "struct")) return TYPE;
if (!strcmp(s, "union")) return TYPE;
if (!strcmp(s, "enum")) return TYPE;
return IDENTIFIER;
}
void gettoken()
{
char* p = this.string;
while ((*p = getchar()) == ' ') ;
if (isalnum(*p)) {
while (isalnum(*++p = getchar()));
ungetc(*p, stdin);
*p = '\0';
this.type = classify_string();
return ;
}
if (*p == '*') {
strcpy(this.string, "pointer to");
this.type = '*';
return ;
}
this.string[1] = '\0';
this.type = *p;
return;
}
void read_to_first_identifier()
{
gettoken();
while (this.type != IDENTIFIER) {
push(this);
gettoken();
}
printf("%s is ", this.string);
gettoken();
}
void deal_with_arrays()
{
while (this.type == '[') {
printf("array ");
gettoken();
if (isdigit(this.string[0])) {
printf("0..%d ", atoi(this.string) - 1);
gettoken();
}
gettoken();
printf("of ");
}
}
void deal_with_function_args()
{
while (this.type != ')') {
gettoken();
}
gettoken();
printf("function returning ");
}
void deal_with_pointers()
{
while (stack[top].type == '*')
{
printf("%s ", pop.string);
}
}
void deal_with_declarator()
{
switch (this.type) {
case '[' :
deal_with_arrays(); break;
case '(' :
deal_with_function_args(); break;
}
deal_with_pointers();
while (top >= 0) {
if (stack[top].type == '(') {
pop;
gettoken(); // read chars after ')'
deal_with_declarator();
} else {
printf("%s ", pop.string);
}
}
}
int main(int argc, char** argv)
{
read_to_first_identifier();
deal_with_declarator();
printf("\n");
return 0;
}
譬如輸入“const char* (*p[])(int);”, 它會告訴你:“p is array of pointer to function returning pointer to char read-only”。(cute?)
指針 | 數組 |
保存數據的地址 | 保存數據 |
間接訪問數據,首先取得指針的內容,把它作爲地址,然後從這個地址提取數據。 如果指針有一個下標[i],就把指針的內容加上i作爲地址,從中提取數據 |
直接訪問數據,a[i]只是簡單的以a+i爲地址取得數據 |
通常用於動態數據結構 | 通常用於存儲固定數據且數據類型相同的元素 |
通常指向匿名數據 | 自身即爲數據名 |
實參 | 所匹配的形式參數 |
數組的數組 char c[8][10] | char (*)[10]; 數組指針 |
指針數組 char *c[15]; | char **c; 指針的指針 |
數組指針(行指針) char (*c)[64] | char (*)[64]; 不改變 |
指針的指針 char** c; | char** c; 不改變 |
#define random(x) (rand() % x) //產生x內的隨機函數
#define RAND_N 1000
//自定義隨機器
void my_random(char *buf1, char *buf2, int count)
{
//判斷範圍
if(random(RAND_N) < RAND_N / count)
{
strcpy(buf1, buf2);
}
}
//主函數
int main()
{
FILE *fp;
int count = 0;
char buf1[100], buf2[100];
if ((fp = fopen("d:/test.txt", "r")) == NULL) {
fprintf(stderr, "open error");
exit(0);
}
if(fscanf(fp, "%s", buf1) == EOF)
{
printf("file is null\n");
return 0;
}
count++;
srand((int)time(0));//設置隨機數種子,srand不能調用兩次以上
for(count++; fscanf(fp, "%s", buf2) != EOF; count++)
{
my_random(buf1, buf2, count);
}
fclose(fp);
printf("隨即讀取的字符串爲 : %s\n", buf1);
return 0;
}