一次C语言编程遇到的问题总结
今天用C语言做了一个简单的用户登录注册存取款等功能的系统,发现有很多功能并不会实现,大概是使用Java太多了导致许多C的知识都忘记了,现在把碰到的问题总结如下:
1、字符串复制问题
java等一些编程语言使用习惯了我们经常会用
String s1 = "abc";String s2 = s1
这种方式来给字符串赋值,但C语言一般使用的是char[]数组来存储字符串,所以在赋值的时候不可以使用单纯的赋值符"=",使用的是string.h头文件中包含的strcpy函数。如:
char a[];
char b[];
strcpy(a,b);
这样可以实现将b的值赋值给a。
2、字符串分隔问题
Java分隔字符串有专门的split函数来实现,C语言也有专门的函数实现,下面是一个实例:
char *p;
char StrLine[] = “a;b;c”;
p = strtok(StrLine,";");
while(p != NULL){
printf("%s\n",p);
p = strtok(NULL,";");
}
strtok函数:
原型:char *strtok(char s[], const char *delim);
介绍:分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。
3、字符串转数字问题
例如现在有int a[3]={'1','2','3'}一个一维数组,如果要将其转换为123这个数字,我们可以这样:
1)计算a的长度,假设为n
2)分别将a[0]~a[n-1]转换为数字
3)这个数字就等于a[0]*10n-1+a[1]*10n-2+...+a[n-1]*100
这种方法确实可以实现,但是这种方法一是费时间二是费内存。
所以C语言有一个函数可以实现这种功能:atoi(a):
int atoi(const char *nptr) 函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0 。特别注意,该函数要求被转换的字符串是按十进制数理解的。
附上简单实现用户登录注册存款取款修改密码的C语言代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h> //定义结构体User代表每一个用户
struct User{
char username[];//用户名
char password[];//密码
int deps;//存款数
}; struct User users[];//用户数组
struct User loginUser;//记录当前登录用户
int usersCount = ;//用户数量,默认为0 //读取文件信息
/*
由于读取文件过程中会自动读取所有数据下面的一个空行,
所以导致读取的userCount即用户数出现错误,比实际大一,
所以在执行完读取文件后,userCount需要减一
*/
void GetFileInfo(){
char *p;
char datas[][];
int i = ;
char fileName[] = "users.txt";
FILE *fp;
char StrLine[];
if((fp = fopen(fileName,"r")) == NULL)
{
printf("读取用户信息失败!");
return;
}
while(!feof(fp))
{
i = ;
fgets(StrLine,,fp);
p = strtok(StrLine," ");
while(p != NULL){
strcpy(datas[i++],p);
//printf("%s\n",p);
p = strtok(NULL," ");
}
strcpy(users[usersCount].username,datas[]);
strcpy(users[usersCount].password,datas[]);
users[usersCount].deps = atoi(datas[]);
usersCount ++;
}
usersCount -= ;
fclose(fp);
printf("读取用户信息成功~\n");
} //写入文件
void Update(){
int i = ;
FILE *fp;
fp = fopen("users.txt","w");
fclose(fp);
fp = fopen("users.txt","w");
for(i = ; i < usersCount; i++){
fprintf(fp,"%s %s %d\n",users[i].username,users[i].password,users[i].deps);
}
fclose(fp);
} //注册功能
struct User regist(){
char regist_username[];
char regist_password[];
struct User newUser;
printf("请输入用户名:");
scanf("%s",®ist_username);
printf("请输入六位密码:");
scanf("%s",®ist_password);
while(regist_password[]==NULL||regist_password[]!=NULL){
printf("密码必须是6位数,请重新输入密码:");
scanf("%s",®ist_password);
}
strcpy(newUser.username,regist_username);
strcpy(newUser.password,regist_password);
newUser.deps = ;//新注册用户余额为0
printf("注册成功!用户:%s\n",regist_username);
return newUser;
} //执行完操作后更新数组
void update(struct User user){
int i;
for(i = ; i < usersCount; i++){
if(strcmp(users[i].username,user.username) == ){
users[i] = user;
break;
}
}
} //登录后菜单选择
void menu(){
void Welcome();
int oper;
int deposit;
int withdraw;
char oldPass[];
char newPass[];
printf("***********\n");
printf("请选择:\n");
printf("1、存款\n");
printf("2、取款\n");
printf("3、查看余额\n");
printf("4、修改密码\n");
printf("5、返回\n");
printf("***********\n");
scanf("%d",&oper);
switch(oper){
case :
printf("请输入要存款的数额:");
scanf("%d",&deposit);
loginUser.deps += deposit;
printf("存款成功!余额为:%d\n",loginUser.deps);
update(loginUser);
Update();
menu();
break;
case :
printf("请输入要取款的数额:");
scanf("%d",&withdraw);
if(loginUser.deps >= withdraw){
loginUser.deps -= withdraw;
printf("取款成功!余额为:%d\n",loginUser.deps);
}else{
printf("余额不足!\n");
}
update(loginUser);
Update();
menu();
break;
case :
printf("用户:%s,您的余额为:%d\n",loginUser.username,loginUser.deps);
menu();
break;
case :
printf("请输入原密码:");
scanf("%s",&oldPass);
if(strcmp(oldPass,loginUser.password) == ){
printf("请输入新密码:");
scanf("%s",&newPass);
while(newPass[]==NULL||newPass[]!=NULL){
printf("密码必须是6位数,请重新输入密码:");
scanf("%s",&newPass);
}
strcpy(loginUser.password,newPass);
printf("更改密码成功!\n");
}else{
printf("原密码输入错误!\n");
}
update(loginUser);
Update();
menu();
break;
case :
Welcome();
}
} //登录功能
void login(){
void Welcome();
char login_username[];
char login_password[];
struct User checkUser;
int i;
printf("请输入用户名:");
scanf("%s",&login_username);
printf("请输入密码:");
scanf("%s",&login_password);
for(i = ; i < usersCount; i++){
if(strcmp(login_username,users[i].username) == ){
if(strcmp(login_password,users[i].password) == ){
loginUser = users[i];
printf("用户 %s欢迎登录!\n",login_username);
menu();
}else{
printf("密码输入错误!\n");
Welcome();
}
}
}
printf("没有这个用户!将返回\n");
Welcome();
} //欢迎界面
void Welcome(){
int select = ;
struct User user;
printf("*********************\n");
printf("欢迎来到ATM自助系统\n");
printf("*********************\n");
printf("请选择操作:\n1、用户登录\n2、用户注册\n3、退出系统\n");
scanf("%d",&select);
if(select == ){
login();
menu();
}else if (select == ){
user = regist();
users[usersCount] = user;
usersCount += ;
Update();
Welcome();
}else if (select == ){
printf("退出成功!");
exit();
}else{
printf("输入错误!将退出系统");
exit();
}
} //主函数
int main()
{
GetFileInfo();
Welcome();
return ;
}
一次C语言编程遇到的问题总结的更多相关文章
- C语言编程实现Linux命令——who
C语言编程实现Linux命令--who 实践分析过程 who命令是查询当前登录的每个用户,它的输出包括用户名.终端类型.登录日期及远程主机,在Linux系统中输入who命令输出如下: 我们先man一下 ...
- 个人c语言编程风格总结
总结一下我个人的编程风格及这样做的原因吧,其实是为了给实验室写一个统一的C语言编程规范才写的.首先声明,我下面提到的编程规范,是自己给自己定的,不是c语言里面规定的. 一件事情,做成和做好中间可能隔了 ...
- Linux下C语言编程实现spwd函数
Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...
- 混合语言编程:启用CLR(公共语言运行时编译)让C#调用C++
前言 关于混合C#和C++的编程方式,本人之前写过一篇博客(参见混合语言编程:C#使用原生的Directx和OpenGL),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct ...
- Linux基础与Linux下C语言编程基础
Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...
- LINUX下C语言编程基础
实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...
- 第二章 C语言编程实践
上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...
- 华为C语言编程规范
DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...
- 9 本免费的 Python 语言编程书籍(转载)
9 本免费的 Python 语言编程书籍 原文地址:http://linuxtoy.org/archives/9-free-python-books.html 2010-03-03 Toy Poste ...
- linux 操作系统下c语言编程入门
2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理 ...
随机推荐
- ws2_32.dll的妙用与删除 (禁网)
ws2_32.dll是Windows Sockets应用程序接口,用于支持Internet和网络应用程序.程序运行时会自动调用ws2_32.dll文件,ws2_32.dll是个动态链接库文件位于系统文 ...
- 图论介绍(Graph Theory)
1 图论概述 1.1 发展历史 第一阶段: 1736:欧拉发表首篇关于图论的文章,研究了哥尼斯堡七桥问题,被称为图论之父 1750:提出了拓扑学的第一个定理,多面体欧拉公式:V-E+F=2 第二阶段( ...
- Windows Server 2008 R2 SP1 中IIS7.5 和 TOMCAT7 整合笔记
Windows Server 2008 R2 SP1 中IIS7.5 和 TOMCAT7 整合笔记 来源:www.roak.com 整合文件在百度网盘或博客盘 配置了N次,64位操作系统真坑爹~~~下 ...
- 6专题总结-动态规划dynamic programming
专题6--动态规划 1.动态规划基础知识 什么情况下可能是动态规划?满足下面三个条件之一:1. Maximum/Minimum -- 最大最小,最长,最短:写程序一般有max/min.2. Yes/N ...
- matlab练习程序(概率路线图PRM)
PRM概率路线图全称 Probabilistic Roadmap,是一种路径规划算法,利用随机撒点的方式将空间抽样并将问题转为图搜索,利用A*或Dijkstra算法找到起始结束节点的最短路径. 可以想 ...
- Python—网络通信编程之udp通信编程
服务端代码 import socket # 1.创建实例,即数据报套接字 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 2.绑 ...
- 074、Java面向对象之构造方法重载
01.代码如下: package TIANPAN; class Book { // 定义一个新的类 private String title; // 书的名字 private double price ...
- 修改Centos7的yum源
以下为修改Centos7的yum源: 1. 备份原镜像文件,便于后期恢复 [root@keepmydream ~]# mv /etc/yum.repos.d/CentOS-Base.repo /etc ...
- swoole之创建子进程
一.代码 <?php /** * 进程就是正在运行的程序的一个实例 * 比如,在某个终端中执行一个PHP脚本,可以认为就是开启了一个进程,会有对应的进程id(pid) * * swoole进程与 ...
- 深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
转自:https://blog.csdn.net/liusicheng2008_liu/article/details/80412586 1 数组的本质 数组是多个元素的集合,在内存中分布在地址相连的 ...