strtok()的簡單使用範例

C语言strtok函数详解

發現一個很好的台灣的博客。可以當作書來閱讀

http://www.cnblogs.com/oomusou/archive/2009/05/10/c_strtok.html

Abstract
strtok()的簡單使用範例。

Introduction
使用環境 : Visual Studio 2008

strtok.c / C

1  /*  
2  (C) OOMusou 2009 http://oomusou.cnblogs.com
3 
4  Filename    : strtok.c
5  Compiler    : Visual C++ 9.0
6  Description : Demo how to use strtok() in C
7  Release     : 05/09/2009 1.0
8  */
9  #include < stdio.h >
10  #include < string .h >
11 
12  int main() {
13    char str[] =   " Hello,World " ;
14    const   char   * del =   " , " ;
15    char   * s = strtok(str, del);
16 
17    while (s != NULL) {
18      printf( " %s\n " , s);
19      s = strtok(NULL, del);
20    }
21 
22    return   0 ;
23  }


執行結果

strtok

完整程式碼下載
strtok.7z

Remark
csie-tw問到,為什麼第二次呼叫時,要使用strtok(NULL, del),這是一個很好的問題,所謂『有code有真相』,來看看Microsoft怎麼實作strtok()。

https://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/strtok.c.htm

1  /* Copyright (c) Microsoft Corporation. All rights reserved. */
2 
3  #include < string .h >
4 
5  /* ISO/IEC 9899 7.11.5.8 strtok. DEPRECATED.
6  * Split string into tokens, and return one at a time while retaining state
7  * internally.
8  *
9  * WARNING: Only one set of state is held and this means that the
10  * WARNING: function is not thread-safe nor safe for multiple uses within
11  * WARNING: one thread.
12  *
13  * NOTE: No library may call this function.
14    */
15 
16  char   * __cdecl strtok( char   * s1, const   char   * delimit)
17  {
18      static   char   * lastToken = NULL; /* UNSAFE SHARED STATE! */
19      char   * tmp;
20 
21      /* Skip leading delimiters if new string. */
22      if ( s1 == NULL ) {
23          s1 = lastToken;
24          if (s1 == NULL)         /* End of story? */
25              return NULL;
26      } else {
27          s1 += strspn(s1, delimit);
28      }
29 
30      /* Find end of segment */
31      tmp = strpbrk(s1, delimit);
32      if (tmp) {
33          /* Found another delimiter, split string and save state. */
34          * tmp =   ' \0 ' ;
35          lastToken = tmp +   1 ;
36      } else {
37          /* Last segment, remember that. */
38          lastToken = NULL;
39      }
40 
41      return s1;
42  }


可以發現,當S1為NULL時,他會使用lastToken這個static char *這個pointer+1繼續搜尋,若S1 != NULL,則當成第一次使用strtok()。

转载于:https://www.cnblogs.com/lzjsky/archive/2010/10/26/1861728.html

#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <errno.h> #include <limits.h> #define MAX_ARGS 64 #define MAX_LINE 1024 int main() { char input[MAX_LINE]; char *args[MAX_ARGS]; char *token; int status; pid_t pid; while (1) { // 提示用户输入 printf("mysh> "); fflush(stdout); // 读取用户输入 printf("【提示】等待用户输入...\n"); if (fgets(input, MAX_LINE, stdin) == NULL) { printf("【提示】EOF 检测到,退出 Shell。\n"); break; } // 移除换行符 input[strcspn(input, "\n")] = '\0'; // 检查退出命令 if (strcmp(input, "exit") == 0) { printf("【提示】用户输入 'exit',准备退出 Shell。\n"); break; } // 打印解析命令 printf("【提示】解析命令: '%s'\n", input); // 解析命令和参数 int i = 0; token = strtok(input, " "); while (token != NULL && i < MAX_ARGS - 1) { args[i++] = token; token = strtok(NULL, " "); } args[i] = NULL; // 忽略空命令 if (i == 0) { printf("【提示】忽略空命令。\n"); continue; } // 创建管道 int pipefd[2]; if (pipe(pipefd) == -1) { perror("【错误】创建管道失败"); exit(EXIT_FAILURE); } // 创建子进程 pid = fork(); if (pid == -1) { perror("【错误】fork失败"); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程 printf("【提示】子进程开始执行命令 '%s'。\n", args[0]); // 关闭管道读端 close(pipefd[0]); // 重定向 stdout 到管道写端 if (dup2(pipefd[1], STDOUT_FILENO) == -1) { perror("【错误】子进程重定向 stdout 失败"); exit(EXIT_FAILURE); } close(pipefd[1]); // 关闭原始写端 // 执行命令 execvp(args[0], args); // 如果exec失败 perror("【错误】execvp失败"); exit(EXIT_FAILURE); } else { // 父进程 // 关闭管道写端 close(pipefd[1]); // 打开管道读端为文件流 FILE *fp = fdopen(pipefd[0], "r"); if (fp == NULL) { perror("【错误】fdopen失败"); exit(EXIT_FAILURE); } char *line = NULL; size_t len = 0; ssize_t nread; int stop_received = 0; printf("【提示】父进程开始读取子进程输出...\n"); // 读取输出 while ((nread = getline(&line, &len, fp)) != -1) { // 去除换行符 if (line[nread - 1] == '\n') { line[nread - 1] = '\0'; } printf("【简易Shell接收,并打印】%s\n", line); // 检测 stop 命令 if (strcmp(line, "stop") == 0) { printf("【提示】检测到 'stop' 命令,准备终止子进程。\n"); if (kill(pid, SIGTERM) == -1 && errno != ESRCH) { perror("【错误】发送 SIGTERM 失败"); } stop_received = 1; break; } } // 清理资源 free(line); fclose(fp); // 会自动关闭 pipefd[0] // 等待子进程结束 if (waitpid(pid, &status, 0) == -1) { perror("【错误】waitpid失败"); } // 打印终止信息 if (stop_received) { printf("【提示】命令被 'stop' 终止。\n"); } else { printf("【提示】子进程执行完成。\n"); } } } printf("【提示】Shell 已退出。\n"); return 0; } 分析上述代码
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值